美文网首页
Spring加载流程

Spring加载流程

作者: ruisheng | 来源:发表于2020-09-21 22:48 被阅读0次

    参考链接:

    https://www.yuque.com/snakes/ayqnq6/fyfefu
    https://blog.csdn.net/tzs_1041218129/article/details/107587706
    https://juejin.im/post/6869407787760222221

    Spring加载流程

    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
    ac.register(AppConfig.class);
    //可以注册普通的bean
    //ac.register(User.class);
    ac.refresh();
    ac.getBean(X.class);
    
    @Configuration
    @ComponentScan("com.ruisheng")
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class AppConfig {
    }
    

    初始化 AnnotatedBeanDefinitionReader

    作用:

    1. 读取spring内部的 唯一的beanFactoryPostProcess 和 5个beanPostProcess。
      • ConfigurationClassPostProcessor (Spring内部唯一的beanFactoryPostProcess的实现类)
      • AutowiredAnnotationBeanPostProcessor
      • CommonAnnotationBeanPostProcessor
      • PersistenceAnnotationBeanPostProcessor
      • EventListenerMethodProcessor
      • DefaultEventListenerFactory
    2. 提供给程序员注册bd(ac.register(AppConfig.class);),一般是用来注册加了@Configuration的类。

    源码解析:

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
       Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
       Assert.notNull(environment, "Environment must not be null");
       this.registry = registry;
       this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
       //使用注解配置时需要注入的一些后置处理器
       AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
    

    初始化 ClassPathBeanDefinitionScanner

    作用:

    1. 程序员能够在外部调用doScan(), 或者 继承该类可以重写scan规则用来动态扫描注解,需要注册到容器。
    2. spring内部是自己重新new 新的对象来扫描。

    主要方法:org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
    (扫描basePackage路径下的文件,把符合条件的类,转成bd。)

    执行 register(AppConfig.class)

    作用:一般是配置类 AppConfig.class,也可以是普通的bean,ac.register(User.class);

    主要代码:org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean
    (解析bean封装为 BeanDefinitionHolder ,注册到 register 中)

    执行 refresh()

    prepareRefresh();

    准备工作包括设置启动时间,是否激活标志位。

    ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

    返回一个factory(DefaultListableBeanFactory)

    prepareBeanFactory(beanFactory);

    准备工厂

    postProcessBeanFactory(beanFactory);

    invokeBeanFactoryPostProcessors(beanFactory);

    作用:

    1. 主要就是扫描包得到类
    2. 通过匹配规则和排除规则得到合适的类
    3. 再通过解析这些类,比如配置类去获取所有的解析出来的类
    4. 将这些扫描解析出来的类,变成bd

    源码分析:

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
       /**
        * getBeanFactoryPostProcessors()得到 1.自定义的且没加@Compoment、2.spring内部维护的BeanDefinitionRegistryPostProcessor实现类。
        * 1.自定义的并且没加@Compoment注解的BeanFactoryPostProcessors实现类。
        * (就是程序员自己写的,并且没有交给spring管理,就是没有加上@Component)
        *  (这里所谓自定义指手动调用:annotationConfigApplicationContext.addBeanFactoryPostProcessor();)
        * 2.得到spring内部的 BeanDefinitionRegistryPostProcessor 实现类
        *   spring内部只有一个实现类:ConfigurationClassPostProcessor
       */
       PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
    
       // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
       // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
       if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
          beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
          beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
       }
    }
    
    1. 执行 BeanDefinitionRegistryPostProcessor

      1. postProcessBeanDefinitionRegistry(registry) 由程序员add的

      2. postProcessBeanDefinitionRegistry(registry) 有特色(比如排序,优先级等等) 由spring内部和程序员(register,注解)

        备注:这里spring内部的有 ConfigurationClassPostProcessor。

      3. postProcessBeanDefinitionRegistry(registry) 剩余的子类 由spring内部和程序员(register,注解)

      4. 所有父方法 postProcessBeanFactory(beanFactory)

    2. 执行 BeanFactoryPostProcessors

      1. postProcessBeanFactory(beanFactory) 由程序员add的
      2. postProcessBeanFactory(beanFactory) 有特色(比如排序,优先级等等) 由spring内部和程序员(register,注解)
      3. postProcessBeanFactory(beanFactory) 剩余的 由spring内部和程序员(register,注解)

    备注1:ConfigurationClassPostProcessor 是优先级最高的被执行的processor(实现了PriorityOrdered接口)。
    ConfigurationClassPostProcessor 最先被处理的原因:如果程序中有自定义的BeanFactoryPostProcessor,那么这个PostProcessor首先得通过ConfigurationClassPostProcessor被解析出来,然后才能被Spring容器找到并执行。(ConfigurationClassPostProcessor不先执行的话,这个Processor是不会被解析的,不会被解析的话也就不会执行了)。

    备注2:在使用mybatis时,一般配置了MapperScannerConfigurer的bean,这个bean就是继承的BeanDefinitionRegistryPostProcessor,所以也是这个地方把扫描的mybatis的接口注册到容器中的。

    registerBeanPostProcessors(beanFactory);

    注册 BeanPostProcessor 的实现类,即从Spring容器中找出的BeanPostProcessor接口的bean,并设置到BeanFactory的属性中。之后bean被实例化的时候会调用这个BeanPostProcessor。

    • 先注册实现PriorityOrdered接口的BeanPostProcessor
    • 在注册实现Ordered接口的BeanPostProcessor
    • 最后注册普通BeanPostProcessor

    为什么要在这里注册呢?不能在前面或后面?????????????????

    initMessageSource();

    初始化国际化资源

    onRefresh();

    registerListeners();

    finishBeanFactoryInitialization(beanFactory);

    完成BeanFactory的bean实例化

    finishRefresh();

    相关文章

      网友评论

          本文标题:Spring加载流程

          本文链接:https://www.haomeiwen.com/subject/xetiyktx.html