• springboot启动过程(3)-refresh方法


    1  springboot在启动的时候,会调用run方法,创建环境设置spring容器,其中包含refresh方法,完成配置类解析,各种beanFactoryPostProcess和beanPostProcessor注册,web内置容器构造,国际化配置初始化等,refresh调用了父类AbstractApplicationContext的refresh方法如下。

    public void refresh() throws BeansException, IllegalStateException {
      Object var1 = this.startupShutdownMonitor;
      synchronized(this.startupShutdownMonitor) {
        this.prepareRefresh();
        ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
        this.prepareBeanFactory(beanFactory);

        try {

          this.postProcessBeanFactory(beanFactory);
          this.invokeBeanFactoryPostProcessors(beanFactory);
          this.registerBeanPostProcessors(beanFactory);
          this.initMessageSource();
          this.initApplicationEventMulticaster();
          this.onRefresh();
          this.registerListeners();
          this.finishBeanFactoryInitialization(beanFactory);
          this.finishRefresh();
        } catch (BeansException var9) {
          if(this.logger.isWarnEnabled()) {
            this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
          }

          this.destroyBeans();
          this.cancelRefresh(var9);
          throw var9;
        } finally {
          this.resetCommonCaches();
        }

      }
    }

     (1)prepareRefresh  在rehresh之前做的准备工作,一是设置spring启动事件,开启活跃状态;二是初始化属性源信息;三是验证必要属性。

     (2)prepareBeanFactory  从spring容器获取BeanFactory并进行相关设置为后续使用做准备。

            *设置用于加载bean的classLoader,设置可以解析bean表达式的表达式解析器,添加属性注册器ResourceEditorRegistrar。

            * 添加ApplicationContextAwarePocessor这个BeanPostProcessor,注入ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、EnvironmentAware几个接口。

           * 设置各种bean,BeanFactory,ResourceLoader,ApplicatioinEventPublisher,ApplicationContext。

           * 配置默认系统属性等。

     (3)postProcessBeanFactory 继上一步beanfactory设置之后进行后续操作,不同spring容器进行不同操作。比如AnnotationConfigEmbeddedWebApplicationContext会对bean进行注入,检查basePackages属性,如果设置了会使用ClassPathBeanDefinitionScanner对basePackage下面的bean进行扫描并注册,如果设置了annotatedClasses属性,就会使用AnnotatedBeanDefinitionReader注册这些带注解的bean。

     (4)invokeBeanFactoryPostProcessors

           * BeanFactoryPostProcessor   其实现类可以在spring容器加载了bean的定义文件之后,在bean实例化之前执行。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息,修改各种配置的元数据,可以配置多个processor,通过设置order属性来控制各个实现类的执行顺序。

           * BeanPostProcessor  BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后,BeanPostProcessor的作用域是容器级的,它只和所在容器有关。如果你在容器中定义了BeanPostProcessor,它仅仅对此容器中的bean进行后置。它不会对定义在另一个容器中的bean进行任何处理。

           * BeanDefinitionRegistryPostProcessor:继承BeanFactoryPostProcessor,作用跟BeanFactoryPostProcessor一样,只不过是使用BeanDefinitionRegistry对bean进行处理

           基于web程序的Spring容器AnnotationConfigEmbeddedWebApplicationContext构造的时候,会初始化内部属性AnnotatedBeanDefinitionReader reader,这个reader构造的时候会在BeanFactory中注册一些post processor,包括BeanPostProcessor和BeanFactoryPostProcessor(比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor);invokeBeanFactoryPostProcessors方法处理BeanFactoryPostProcessor的逻辑是:

    从Spring容器中找出BeanDefinitionRegistryPostProcessor类型的bean(这些processor是在容器刚创建的时候通过构造AnnotatedBeanDefinitionReader的时候注册到容器中的),然后按照优先级分别执行,优先级的逻辑如下:

         1)实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行

                 2)实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行

         3)没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行

        ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。这个ConfigurationClassPostProcessor会去BeanFactory中找出所有有@Configuration注解的bean,然后使用ConfigurationClassParser去解析这个类。ConfigurationClassParser内部有个Map类型的configurationClasses属性用于保存解析的类,ConfigurationClass是一个对要解析的配置类的封装,内部存储了配置类的注解信息、被@Bean注解修饰的方法、@ImportResource注解修饰的信息、ImportBeanDefinitionRegistrar等都存储在这个封装类中。这里ConfigurationClassPostProcessor最先被处理还有另外一个原因是如果程序中有自定义的BeanFactoryPostProcessor,那么这个PostProcessor首先得通过ConfigurationClassPostProcessor被解析出来,然后才能被Spring容器找到并执行。(ConfigurationClassPostProcessor不先执行的话,这个Processor是不会被解析的,不会被解析的话也就不会执行了)。

      invokeBeanFactoryPostProcessors方法总结来说就是从Spring容器中找出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的实现类并按照一定的规则顺序进行执行。 其中ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor优先级最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化。

     (5)registerBeanPostProcessors  

      使用了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。这里的过程跟invokeBeanFactoryPostProcessors类似:
        1)先找出实现了PriorityOrdered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
        2)找出实现了Ordered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
        3)没有实现PriorityOrdered和Ordered接口的BeanPostProcessor加到BeanFactory的BeanPostProcessor集合中
      这些已经存在的BeanPostProcessor在postProcessBeanFactory方法中已经说明,都是由AnnotationConfigUtils的registerAnnotationConfigProcessors方法注册的。这些BeanPostProcessor包括有AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)、RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)、CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。如果是自定义的BeanPostProcessor,已经被ConfigurationClassPostProcessor注册到容器内。
      这些BeanPostProcessor会在这个方法内被实例化(通过调用BeanFactory的getBean方法,如果没有找到实例化的类,就会去实例化)。

     (6)initMessageSource  初始化国际化属性。

     (7)initApplicationEventMulticaster  初始化事件广播器,用于发布事件。EventPublishingRunlistener会监听事件,在run函数之前contextPrepared时候已经注入了。这个时候不需要注册,只要拿到BeanFactory的广播器直接设置到spring容器,如果没有再自己初始化。

     (8)onRefresh  不同容器各自实现,比如ConfigEmbeddedWebApplicationContext中会调用createEmbeddedServletContainer方法去创建内置的Servlet容器,目前只支持三种 tomcat,jetty,undertow。

     (9)registerListeners 把spring容器内的listener和beanfactory的listener都添加到广播器中。

     (10)finishBeanFactoryInitialization  实例化BeanFactory 中已经被注册但是没被实例化的所有实例,懒加载除外。比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,都会初始化。初始化的过程中各种BeanPostProcessor开始起作用。

     (11)finishRefresh 初始化生命周期处理器LifecycleProcessor并调用其onrefresh方法,找到SmartLifecycle接口的所有实现类并调用start方法,发布事件告知listener,如果设置了JMX相关属性,还会调用LiveBeansView的registerApplicationContext方法。

  • 相关阅读:
    Spring Boot下的一种导入Excel文件的代码框架
    Spring Boot下的一种导出CSV文件的代码框架
    Spring Boot下的一种导出Excel文件的代码框架
    使用系统参数表,提升系统的灵活性
    折纸效果! Cocos Creator 3.0
    弹性跟随相机!3D入门教程!
    dotnet OpenXML 读取 PPT 主序列进入退出强调动画
    dotnet C# 调用委托的 GetInvocationList 的对象分配
    WPF 下拉框选项做鼠标 Hover 预览效果
    WPF 后台代码做 TranslateTransform 的动画
  • 原文地址:https://www.cnblogs.com/lkdirk/p/7145941.html
Copyright © 2020-2023  润新知