spring初始化&循环引用

一、寻找核心方法

// == 入口
public static void main(String[] args) {
    SpringApplication.run(SpringRunner.class, args);
}

// == 调用链
org.springframework.boot.SpringApplication#run(java.lang.Class, java.lang.String...)
org.springframework.boot.SpringApplication#run(java.lang.Class[], java.lang.String[])
org.springframework.boot.SpringApplication#run(java.lang.String...)
org.springframework.boot.SpringApplication#refreshContext
org.springframework.boot.SpringApplication#refresh

记住refresh方法,它非常重要

观察它的内部实现:

// ##### IOC容器初始化 ##### 
// 告知子类要初始化BeanFactory
// BeanDefinition信息的读取是在子类的refreshBeanFactory()方法里完成的
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 准备bean工厂以在此上下文中使用。
this.prepareBeanFactory(beanFactory);

// ##### 著名的九大方法 ##### 
try {
    // 设置beanFactory的后置处理
    postProcessBeanFactory(beanFactory);
    // 调用beanFactory的后置处理,如springboot自动装配获取配置的Entity
    invokeBeanFactoryPostProcessors(beanFactory);
    // 注册beanFactory的后置处理
    registerBeanPostProcessors(beanFactory);
    // 初始化上下文的消息
    initMessageSource();
    // 初始化上下的事件
    initApplicationEventMulticaster();
    // 初始化一些特殊的bean
    onRefresh();
    // 检查一些监听的bean并注册到容器中
    registerListeners();
    // Instantiate all remaining (non-lazy-init) singletons,spring bean对象初始化在这里
    finishBeanFactoryInitialization(beanFactory);
    // 发布容器事件,结束Refresh过程
    finishRefresh();

二、注册和扫描

本节深入分析构建BeanFactory的过程。

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

// == 调用链    
org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
// -- 分析注解方式注入
org.springframework.web.context.support.AnnotationConfigWebApplicationContext#loadBeanDefinitions

1.向容器注册对象信息

注入的本质就是向容器(也有叫上下文的,就是Context的直译)——实质就是一个Map注册类的描述信息

用代码描述就是:
beanDefinitionMap.put(BeanDefinition)

看看具体实现:

// == 注册逻辑
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {
   AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);

   if (!this.annotatedClasses.isEmpty()) {
      reader.register(this.annotatedClasses.toArray(new Class[this.annotatedClasses.size()]));
   }
}

// == 调用链
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class)
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean

这个方法值得细说一下:

 void doRegisterBean(Class annotatedClass, @Nullable Supplier instanceSupplier, @Nullable String name,
            @Nullable Class[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

    //## 被注解修饰的对象,会被封装成BeanDefinition结构
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

    //为注解Bean定义生成Bean名称
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    // BeanDefinition再次封装
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);

    // ## 注入
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

// == 调用链
org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition
// -- 前面创建的工厂是DefaultListableBeanFactory
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition

最终的注入逻辑:

// 存储注册信息的BeanDefinition
private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
    // ## 注入的本质
    this.beanDefinitionMap.put(beanName, beanDefinition);
}

2.扫描指定package的配置信息

无它,只为扩大扫描范围
默认只注入SpringRunner(Starter类)的子包

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) {  
   //为容器设置类路径Bean定义扫描器
   ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);

   if (!this.basePackages.isEmpty()) {
      scanner.scan(this.basePackages.toArray(new String[this.basePackages.size()]));
   }
}

// == 调用链
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#scan
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan

protected Set doScan(String... basePackages) {
    //遍历扫描所有给定的包
    for (String basePackage : basePackages) {
        // ## 同样执行注入流程
        registerBeanDefinition(definitionHolder, this.registry);
    }
}

未完待续(懒癌发作……)

你可能感兴趣的:(spring)