Spring boot 2.x 源碼分析- SpringApplication 啟動分析


springboot 自動裝配原理概述:

      1.當啟動Springboot應用程序時,會先創建 SpringApplication 對象。在對象的構造函數中會進行參數的初始化工作,最主要的是判斷當前應用程序的類型以及讀取初始化器和監聽器。在這個過程中會加載整           個應用程序中的spring.factories文件,將文件的內容放到緩存對象中,方便后續獲取。

      2. SpringApplication創建完成后,開始執行run方法,進行整個應該程序的啟動。在啟動過程中,最主要的有兩個方法,prepareContext,refreshContext方法。程序會在這兩個方法中完成自動裝配的核心功                能。具體包括 上下文對象創建,banner打印,異常報告器的准備等邏輯處理,為后續程序完整啟動做准備。

      3. 在 prepareContext 方法中,主要完成對上下對象的初始化操作,具體包括屬性值的設置。其中有一個非常重要的方法load。load 主要將當前啟動類作為一個bean,以beanDefinition的配置注冊到                          beanFactory 中,為后續調用 BeanFactoryPostProcessor的增強方法做准備。 后續 執行時,發現程序中有@Configuration配置時,會觸發@SrpingBootApplication,@EnableAutoConfiguration 等注解的解析工作。

      4. 在 refreshContext 方法中,會進行整個容器的刷新過程。這個方法會間接調用spring中refresh方法,完成整個Spring應用程序的啟動。其中在依次調用 BeanFactoryPostProcessor 實現類的方法時,會使             用到一個主要的實現類 ConfigurationClassPostProcessor 處理類。在調用該類 postProcessBeanDefinitonRegister 方法,緊接着調用 postProcessBeanFactory方法時會進行解析配置相關的注解。主要包             括 @PropertySource, @ComponentScan, @Bean,@Import 等注解,其中最重要的時@Import注解。

      5. 在解析@Import注解時,會調用一個 getImports 方法,從主要類開始遞歸解析注解,找到所有@Import注解信息,然后再調用 processImport方法對Import類進行分類處理,此處主要識別                                        AutoConfigurationImportSelect 歸屬的ImportSelect 子類,后續過程會調用 deferredImportSelectorHandler 中的process 方法,來加載所有的 EnableAutoConfiguration 的配置。

 

一.  SpringApplication 創建:

        org.springframework.boot.SpringApplication(Class<?>... primarySources)

            org.springframework.boot.SpringApplication#SpringApplication(ResourceLoader, Class<?>...)

        1. 設置資源引導(ResourceLoader)。

        2. 設置主要資源信息(primarySources)。

        3. 推斷Web應用類型(webApplicationType)。默認有三種:java標准的 SERVLET 類型, 反應式 REACTIVE 類型,以及未知的 NONE 類型。

        4. 設置初始化程序(ApplicationContextInitializer)對象實例列表 (List<ApplicationContextInitializer<?>>)。即讀取 jar 文件中 META-INF/spring.factories 配置的所有 org.springframework.context.ApplicationContextInitializer 實現。

         常用的實現類:

org.springframework.boot.devtools.restart.RestartScopeInitializer 
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
org.springframework.boot.context.ContextIdApplicationContextInitializer
org.springframework.boot.context.config.DelegatingApplicationContextInitializer
org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

       5. 設置監聽器(ApplicationListener)對象實例列表 (List<ApplicationListener<?>>)。即 jar 文件中 META-INF/spring.factories 配置的所有 org.springframework.context.ApplicationListener 實現。

        常用的實現類:

org.springframework.boot.devtools.restart.RestartApplicationListener
org.springframework.boot.devtools.logger.DevToolsLogFactory.Listener
org.springframework.boot.autoconfigure.BackgroundPreinitializer
org.springframework.boot.ClearCachesApplicationListener
org.springframework.boot.builder.ParentContextCloserApplicationListener
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor
org.springframework.boot.context.FileEncodingApplicationListener
org.springframework.boot.context.config.AnsiOutputApplicationListener
org.springframework.boot.context.config.ConfigFileApplicationListener
org.springframework.boot.context.config.DelegatingApplicationListener
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener
org.springframework.boot.context.logging.LoggingApplicationListener
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

  6. 推斷運行程序的主類類型(mainApplicationClass)。

    /**
     * Create a new {@link SpringApplication} instance. The application context will load
     * beans from the specified primary sources (see {@link SpringApplication class-level}
     * documentation for details. The instance can be customized before calling
     * {@link #run(String...)}.
     * @param resourceLoader the resource loader to use
     * @param primarySources the primary bean sources
     * @see #run(Class, String[])
     * @see #setSources(Set)
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = deduceMainApplicationClass();
    }
View Code

 

二. Springboot 的SPI機制加載類邏輯

      org.springframework.boot.SpringApplication#getSpringFactoriesInstances(Class<T> type)
             org.springframework.boot.SpringApplication#getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args)
                  org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames(Class<?> factoryType, ClassLoader classLoader)
                  org.springframework.boot.SpringApplication#createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names)

       1. 獲得當前環境的類加載器。默認是從 Thread.currentThread().getContextClassLoader() 獲取的。

                JDK8中為           :sun.misc.Launcher$AppClassLoader。

                JDK9及以后版本:jdk.internal.loader.ClassLoaders$AppClassLoader

       2. 從 META-INF/spring.factories 配置中尋找 type 實現類的配置列表。如果已加載,則從本地緩存中讀取。

       3. 根據傳遞的參數,實例化 type 的實例。

       4. 排序 type 實現類列表,並返回。

    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = getClassLoader();
        // Use names and ensure unique to protect against duplicates
        Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }

 

三. SpringApplication#run() 分析

       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...)

      (一) run 方法概述:

      1. 創建 StopWatch 實例,記錄當前開始時間,以及任務名稱等信息。

      2. 設置系統屬性 java.awt.headless 值。默認為true。Headless是指服務器的無顯示設備狀態。

      3.  獲取程序運行監聽器輔助類(SpringApplicationRunListeners)實例,並觸發 starting() 事件。SpringApplicationRunListeners#starting()

            SpringApplicationRunListener 監聽 SpringApplication 類執行run方法觸發的七個事件。這七個事件對應運行時的七個周期節點,開發人員根據需要,可以在相關節點進行擴展。

            該接口默認只有一個實現 EventPublishingRunListener 類。創建時注入了 SpringApplication 類,事件廣播類 SimpleApplicationEventMulticaster 實例。最終將SpringApplication 事件監聽器和Spring的事件監聽器關聯上。

      4.  創建 請求參數包裝類實例。

      5. 預處理環境變量信息。SpringApplication#prepareEnvironment()

      6.  設置是否忽略 beanInfo 信息參數。 spring.beaninfo.ignore

      7.  打印 Banner 信息。SpringApplication#printBanner() 。創建對象 SpringApplicationBannerPrinter 實例,打印Banner。

      8.  根據Web應用類型(webApplicationType) 創建程序上下文實例(ConfigurableApplicationContext)。

                 SERVLET      AnnotationConfigServletWebServerApplicationContext

                REACTIVE     AnnotationConfigReactiveWebServerApplicationContext

               默認類型          AnnotationConfigApplicationContext

               當前環境創建   AnnotationConfigServletWebServerApplicationContext 實例,進行spring 邏輯的處理。

      9.  獲得 異常報告處理接口(SpringBootExceptionReporter)的所有實現,並創建實例。默認實現類: org.springframework.boot.diagnostics.FailureAnalyzers

      10. 預處理 程序上下文。SpringApplication#prepareContext()

      11. 刷新 程序上下文。注冊程序停機Hook,並調用Spring 的 AbstractApplicationContext#refresh() 方法,進行Spring 的程序運行環境的創建。

      12. 刷新 程序上下文后置處理。留給用戶擴展的方法。

      13. 調用 StopWatch 實例stop() 方法,標記任務執行完成,記錄任務結束時間。

      14. 執行 started() 方法。SpringApplicationRunListeners#started()

      15. 找到注入的所有 ApplicationRunner,CommandLineRunner 實現類,依次調用。默認沒用實現類。

      16. 執行 runing() 方法。SpringApplicationRunListeners#running(ConfigurableApplicationContext context)。

      17. 如果出現異常,進行異常處理。

     SpringApplication#handleRunFailure(ConfigurableApplicationContext context, Throwable exception, Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners)

   (二) 重要步驟詳解

     SpringApplicationRunListeners#starting() 事件詳解:

           org.springframework.boot.SpringApplicationRunListeners#starting()
                  org.springframework.boot.context.event.EventPublishingRunListener#starting()
                      this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));

                      org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent)

     常見支持 ApplicationStartingEvent 事件的監聽器有如下幾個:  

             org.springframework.boot.devtools.restart.RestartApplicationListener,
             org.springframework.boot.context.logging.LoggingApplicationListener,
             org.springframework.boot.autoconfigure.BackgroundPreinitializer,
             org.springframework.boot.context.config.DelegatingApplicationListener,
             org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

RestartApplicationListener 監聽器, 程序調試時使用的,方便自動重啟服務。經過相關邏輯處理后,設置使用 org.springframework.boot.devtools.restart.RestartLauncher 類實現服務的重新啟動。

org.springframework.boot.devtools.restart.RestartApplicationListener#onApplicationEvent(ApplicationEvent event)
      org.springframework.boot.devtools.restart.RestartApplicationListener#onApplicationStartingEvent(ApplicationStartingEvent event)
            org.springframework.boot.devtools.restart.Restarter#initialize(java.lang.String[], boolean, org.springframework.boot.devtools.restart.RestartInitializer, boolean)
                  org.springframework.boot.devtools.restart.Restarter#initialize(boolean)
                         org.springframework.boot.devtools.restart.Restarter#immediateRestart

 

LoggingApplicationListener  監聽器,進行日志的初始化處理。當前環境配置的是Logback日志實現。

     org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationEvent(ApplicationEvent event)
         org.springframework.boot.context.logging.LoggingApplicationListener#onApplicationStartingEvent(ApplicationStartingEvent event)
              org.springframework.boot.logging.logback.LogbackLoggingSystem#beforeInitialize()

 

BackgroundPreinitializer 監聽器,后台線程早期初始化處理器。 當前事件不觸發邏輯處理。

DelegatingApplicationListener 監聽器,  和 EventPublishingRunListener 類功能類似。當前事件不觸發邏輯處理。

LiquibaseServiceLocatorApplicationListener 監聽器, 當前事件不觸發。LiquiBase是一個用於數據庫重構和遷移的開源工具,通過日志文件的形式記錄數據庫的變更,然后執行日志文件中的修改,將數據庫更新或回滾到一致的狀態。

 

        環境變量預處理 SpringApplication#prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments)

        1. 創建環境變量(ConfigurableEnvironment)的實現類。          

                        SERVLET           StandardServletEnvironment
                        REACTIVE         StandardReactiveWebEnvironment
                        default                StandardEnvironment

        2.  用 程序啟動參數 和 默認環境變量配置處理。

        3.  進行環境屬性 configurationProperties 處理。ConfigurationPropertySources.attach(environment)。

        4.  執行SpringApplicationRunListeners#environmentPrepared(ConfigurableEnvironment environment)方法,觸發 ApplicationEnvironmentPreparedEvent 事件。

             滿足 ApplicationEnvironmentPreparedEvent  事件的監聽器:      

                org.springframework.boot.devtools.restart.RestartApplicationListener, 未觸發相關邏輯處理。
                org.springframework.boot.context.config.ConfigFileApplicationListener, 配置處理邏輯

                          讀取 EnvironmentPostProcessor 接口實現列表,依次處理屬性配置:

                                  org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,
                                  org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,
                                  org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
                                  org.springframework.boot.context.config.ConfigFileApplicationListener,
                                  org.springframework.boot.devtools.env.DevToolsHomePropertiesPostProcessor,
                                  org.springframework.boot.devtools.env.DevToolsPropertyDefaultsPostProcessor,
                                  org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor

                org.springframework.boot.context.config.AnsiOutputApplicationListener,
                org.springframework.boot.context.logging.LoggingApplicationListener,  日志處理初始化
                org.springframework.boot.autoconfigure.BackgroundPreinitializer,  后台線程早期初始化處理。
                org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,  打印ClassPath路徑。
                org.springframework.boot.context.config.DelegatingApplicationListener, 委派處理。此處無滿足條件,無處理邏輯。
                org.springframework.boot.context.FileEncodingApplicationListener   文件字符配置檢查  spring.mandatory-file-encoding

        5.  將環境變量信息綁定到應用程序上。 Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));

        6.  重新進行環境屬性 configurationProperties 處理。ConfigurationPropertySources.attach(environment)。

 

      根據Web應用類型(webApplicationType) 創建程序上下文實例(ConfigurableApplicationContext)

         AnnotationConfigServletWebServerApplicationContext 實例化分析:

             1. 創建BeanFactory 默認實現類 DefaultListableBeanFactory 實例。

             2.  創建  AnnotatedBeanDefinitionReader 實例,添加 BeanDefinition 配置處理器。

                   org.springframework.context.annotation.AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry)
                        org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)
                             org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)
                                  org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry)
                                       org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(BeanDefinitionRegistry, Object)

                    ① 如果 BeanFactory 中沒用配置 org.springframework.context.annotation.internalConfigurationAnnotationProcessor 名稱的bean,則使用默認的 ConfigurationClassPostProcessor。

                    ② 如果 BeanFactory 中沒用配置 org.springframework.context.annotation.internalAutowiredAnnotationProcessor 名稱的bean,則使用默認的 AutowiredAnnotationBeanPostProcessor。

                    ② 如果 BeanFactory 中沒用配置 org.springframework.context.annotation.internalCommonAnnotationProcessor 名稱的bean,則使用默認的 CommonAnnotationBeanPostProcessor。

                    ② 如果 BeanFactory 中配置JPA實現,但沒用配置 org.springframework.context.annotation.internalPersistenceAnnotationProcessor 名稱的bean,則使用默認的 PersistenceAnnotationBeanPostProcessor。

                    ② 如果 BeanFactory 中沒用配置 org.springframework.context.event.internalEventListenerProcessor 名稱的bean,則使用默認的 EventListenerMethodProcessor。

                    ② 如果 BeanFactory 中沒用配置 org.springframework.context.event.internalEventListenerFactory 名稱的bean,則使用默認的 DefaultEventListenerFactory。

             3.  創建  ClassPathBeanDefinitionScanner 實例,掃描 @Component, @Repository, @Service, @Controller 配置的工具類。

 

      預處理程序上下文(ConfigurableApplicationContext)。SpringApplication#prepareContext()

        1.  設置上下文環境(ConfigurableApplicationContext) 的環境變量信息。

        2.  處理上下文環境(ConfigurableApplicationContext) 相關信息。默認主要設置 ApplicationConversionService 實例。

        3.  遍歷執行 ApplicationContextInitializer 接口實現,進行相關初始化處理。

                   常用的 ApplicationContextInitializer  接口實現類:

                            org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer 

                                     向上下文環境(ConfigurableApplicationContext) 添加(CachingMetadataReaderFactoryPostProcessor) 處理器。
                            org.springframework.boot.context.config.DelegatingApplicationContextInitializer,

                                   讀取 context.initializer.classes 配置,委派處理自定義的 ApplicationContextInitializer  實現。
                            org.springframework.boot.context.ContextIdApplicationContextInitializer,

                                   向上下文環境(ConfigurableApplicationContext) 注冊 ContextId 實例。
                            org.springframework.boot.devtools.restart.RestartScopeInitializer,

                                   向上下文環境(ConfigurableApplicationContext) 注冊 RestartScope 實例。
                            org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener,

                                   添加 ConditionEvaluationReportLoggingListener 監聽器。
                            org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,

                                  向上下文環境(ConfigurableApplicationContext) 添加(ConfigurationWarningsPostProcessor) 處理器。
                            org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer,

                                  添加 RSocketPortInfoApplicationContextInitializer.Listener 監聽器。
                            org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

                                  添加 ServerPortInfoApplicationContextInitializer 監聽器。

        4.  執行 SpringApplicationRunListeners#contextPrepared() 方法,觸發 ApplicationContextInitializedEvent 事件。

              滿足 ApplicationContextInitializedEvent  事件的監聽器:

                org.springframework.boot.devtools.restart.RestartApplicationListener, 未滿足執行條件,無處理邏輯。
                org.springframework.boot.autoconfigure.BackgroundPreinitializer,  未滿足執行條件,無處理邏輯。
                org.springframework.boot.context.config.DelegatingApplicationListener  未滿足執行條件,無處理邏輯。

        5.  打印程序啟動日志信息。

        6.  設置 beanFactory 信息。注冊 ApplicationArguments 和 Banner 的 bean實例。根據配置添加 LazyInitializationBeanFactoryPostProcessor 處理器。

        7.  加載所有 bean 資源配置信息,並轉換成 BeanDefinition 配置對象。

                  創建 BeanDefinitionLoader 實例,設置 資源對象, 並創建讀取資源的默認實現類, AnnotatedBeanDefinitionReader, XmlBeanDefinitionReader, GroovyBeanDefinitionReader,ClassPathBeanDefinitionScanner。然后根據資源對象的類型,讀取資源里面配置的 BeanDefinition  信息。spring boot 默認是使用 AnnotatedBeanDefinitionReader 實現讀取資源。

        8.  執行SpringApplicationRunListeners#contextLoaded() 方法,觸發ApplicationPreparedEvent 事件。

              滿足 ApplicationPreparedEvent 事件的監聽器:

                      org.springframework.boot.devtools.restart.RestartApplicationListener, 

                           執行Restarter#prepare(org.springframework.context.ConfigurableApplicationContext) 方法。
                      org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,

                           解析 VCAP(又名 Cloud Foundry)元數據。
                      org.springframework.boot.context.config.ConfigFileApplicationListener,

                           添加配置文件相關的 PropertySourceOrderingPostProcessor 處理器。
                      org.springframework.boot.context.logging.LoggingApplicationListener,

                          注冊日志相關的 LogbackLoggingSystem 和 LoggerGroups 的 bean 實例。
                      org.springframework.boot.autoconfigure.BackgroundPreinitializer,  未滿足執行條件,無處理邏輯。
                      org.springframework.boot.context.config.DelegatingApplicationListener, 未滿足執行條件,無處理邏輯。
                      org.springframework.boot.devtools.logger.DevToolsLogFactory$Listener  日志處理。

 

         執行 started() 方法。SpringApplicationRunListeners#started()

            滿足 ApplicationStartedEvent 事件監聽器,           

                  org.springframework.boot.devtools.restart.RestartApplicationListener, 未滿足執行條件,無處理邏輯。
                  org.springframework.boot.autoconfigure.BackgroundPreinitializer,  未滿足執行條件,無處理邏輯。
                  org.springframework.boot.context.config.DelegatingApplicationListener 未滿足執行條件,無處理邏輯。

          執行 AvailabilityChangeEvent.publish(context, LivenessState.CORRECT) 方法,觸發 AvailabilityChangeEvent 事件:       

                org.springframework.boot.devtools.restart.RestartApplicationListener, 未滿足執行條件,無處理邏輯。
                org.springframework.boot.context.config.DelegatingApplicationListener, 未滿足執行條件,無處理邏輯。
                org.springframework.boot.availability.ApplicationAvailabilityBean 記錄 AvailabilityChangeEvent 事件。

            

       執行 runing() 方法。SpringApplicationRunListeners#running(ConfigurableApplicationContext context)

         滿足 ApplicationReadyEvent 事件監聽器:  

           org.springframework.boot.devtools.restart.RestartApplicationListener,  調用 Restarter.getInstance().finish() 方法。
           org.springframework.boot.autoconfigure.BackgroundPreinitializer,  檢查后台線程早期初始化處理器是否完成,如果沒完成則等待。
           org.springframework.boot.context.config.DelegatingApplicationListener, 未滿足執行條件,無處理邏輯。
           org.springframework.boot.devtools.autoconfigure.ConditionEvaluationDeltaLoggingListener  重啟時相關信息。

     執行 AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC) 方法,觸發 AvailabilityChangeEvent 事件:        

         org.springframework.boot.devtools.restart.RestartApplicationListener, 未滿足執行條件,無處理邏輯。
         org.springframework.boot.context.config.DelegatingApplicationListener, 未滿足執行條件,無處理邏輯。
         org.springframework.boot.availability.ApplicationAvailabilityBean  記錄 AvailabilityChangeEvent 事件。

 

      當出現異常,進行異常處理

        SpringApplication#handleRunFailure(ConfigurableApplicationContext context,

                                                           Throwable exception,

                                                          Collection<SpringBootExceptionReporter> exceptionReporters,

                                                         SpringApplicationRunListeners listeners)

        1.  獲得退出異常的退出碼(exitCode)。如果找到了,則觸發  ExitCodeEvent 事件, 並用 SpringBootExceptionHandler 記錄退出碼信息。

        2.  執行 SpringApplicationRunListeners#failed()方法,觸發  ApplicationFailedEvent 事件,進行相關事件處理。

        3.  SpringBootExceptionHandler 記錄異常類信息。

 

四. Spring 的 PostProcessor 分析

      Spring 調用 BeanFactoryPostProcessor  處理器,進行 bean 配置的處理。

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)

SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor,
ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor@7baba5c4,
ConfigFileApplicationListener$PropertySourceOrderingPostProcessor

    (一):依次執行BeanFactory的 BeanDefinitionRegistryPostProcessor 處理器 BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法。

          1. SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor  注冊在 ConfigurationClassPostProcessor 和 Spring Boot 之間共享元數據的bean對象SharedMetadataReaderFactoryBean。

          2.ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor  檢查@ComponentScan 配置是否有問題。即是否配置了 org.springframework 和 org 包掃描路徑。

          3. ConfigurationClassPostProcessor  處理注冊配置的 BeanDefinition 信息。spring中所有注解配置,都是通過這個類來實現的。                

                  org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
                       org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions(BeanDefinitionRegistry registry)

                       ①   獲取當前 BeanDefinitionRegistry 上加載的所有 BeanDefinition 配置。

                       ②   循環處理加載的 BeanDefinition 配置。如果滿足指定條件,則將其添加到 待處理配置bean列表中(configCandidates)。

                                  如果 BeanDefinition 實例以及被 ConfigurationClassPostProcessor 類處理,則不進行后續處理。

                                  如果沒有經過處理,則判斷 BeanDefinition 配置的類是否使用 @Configuration 修飾。或者是否使用 @Component, @ComponentScan, @Import, @ImportResource 修飾,或者方法是否使                            用 @Bean 修飾。

                       ③    根據當前環境,創建 ConfigurationClassParser 實例。

                              ConfigurationClassParser(MetadataReaderFactory metadataReaderFactory, 

                                                                       ProblemReporter problemReporter, Environment environment,

                                                                       ResourceLoader resourceLoader, 

                                                                      BeanNameGenerator componentScanBeanNameGenerator,

                                                                      BeanDefinitionRegistry registry)     

                         ④   使用 ConfigurationClassParser  工具類實例,循環處理 @Configuration 修飾的類BeanDefinition 配置。

                                  a. 依次解析 @Component, @PropertySource,@ComponentScan,@ComponentScans,@Import,@ImportResource,@Bean 注解的配置,

                                      或實現 ImportBeanDefinitionRegistrar 接口的配置。

                                  b.  校驗 解析的配置。

                                  c.  創建讀取 Bean配置的  ConfigurationClassBeanDefinitionReader  實例reader。

                                  d.  使用reader讀取 ConfigurationClass 配置的 BeanDefinition 信息。

                                  e.  重新獲取 BeanDefinitionRegistry 上加載的所有 BeanDefinition 配置,去掉已經解析過的 @Configuration 配置。

                                  f.  檢查是否還有 待處理配置 bean 。如果有則循環 a 至 e 步驟。

 

    (二):依次執行BeanFactory的 BeanFactoryPostProcessor 處理器 BeanFactoryPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 方法   

             SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor,  無處理邏輯
             ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor,   無處理邏輯
             ConfigurationClassPostProcessor   處理配置類。如果配置類 中屬性 ConfigurationClassPostProcessor.configurationClass = "full"(即@Configuration(proxyBeanMethods=true)),則將beanClass設置為cglib代理的類。ConfigurationClassEnhancer#enhance(Class<?> configClass, @Nullable ClassLoader classLoader)

 

       ConfigFileApplicationListener$PropertySourceOrderingPostProcessor  無滿足條件,無處理邏輯


        PropertySourcesPlaceholderConfigurer  解析 ${...} 配置

            PropertySourcesPlaceholderConfigurer#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
                 PropertySourcesPlaceholderConfigurer#processProperties(ConfigurableListableBeanFactory, ConfigurablePropertyResolver)
                      PlaceholderConfigurerSupport#doProcessProperties(ConfigurableListableBeanFactory, StringValueResolver)

         1.   創建 BeanDefinitionVisitor 實例visitor。

         2.   依次取出所有 BeanDefinition  配置,使用 visitor 實例解析 BeanDefinition  配置的屬性。即將 ${...} 配置替換成實際的值。

         3.   依次取出所有 別名 配置,使用 valueResolver 實例解析 alias, registeredName 值。即將 ${...} 配置替換成實際的值。

         4.   將 valueResolver 解析器添加到 beanFactory 上。


       EventListenerMethodProcessor,  將EventListenerFactory類型bean 取出,添加到  eventListenerFactories 屬性上。處理將 @EventListener 修飾的類包裝成ApplicationListener 。
       ErrorMvcAutoConfiguration$PreserveErrorControllerTargetClassPostProcessor  確保在使用 AOP 時保留 ErrorController MVC bean 的目標類。

 

     (三):在創建bean 對象實例時,再通過 BeanPostProcessor 進行bean對象實例的增強處理。在創建 bean 實例時,有六個位置調用BeanPostProcessor  實現進行bean增強處理。

          1.   開始創建  bean  實例之前,嘗試 快捷方式創建 bean 實例。如果創建成功,則創建邏輯不再執行。

                AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                      AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
                           AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
                                 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
                           AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                                BeanPostProcessor#postProcessAfterInitialization(Object bean, String beanName)

                

               ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor   無處理邏輯
               CommonAnnotationBeanPostProcessor  無處理邏輯
               AutowiredAnnotationBeanPostProcessor  無處理邏輯

               ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor  無處理邏輯

 

             2.   創建 bean 實例后,檢查 BeanDefinition 配置是否需要合並。

                AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                      AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                            AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName)
                                  MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)

            

                 ApplicationListenerDetector, 檢查配置的 beanDefinition 是否是 ApplicationListener 類型。如果是,則添加到成員字段上。

                CommonAnnotationBeanPostProcessor  檢查 beanType 的字段和方法是否使用 @PostConstruct 和 @PreDestroy標識,如果是,則包裝成 LifecycleMetadata 實例,為后續處理進行准備。

                                                                                 檢查 beanType 的字段和方法是否使用 @WebServiceRef, @EJB 和 @Resource標識,如果是,則包裝成 WebServiceRefElement, EjbRefElement,                                                                                                   ResourceElement 實例,添加到 AutowiredAnnotationBeanPostProcessor#injectionMetadataCache 中為后續依賴注入處理進行准備。    

                AutowiredAnnotationBeanPostProcessor  檢查 beanType 的字段和方法是否使用 @Autowired 和 @Value 標識。如果是,則將解析后包裝成 AutowiredFieldElement,  AutowiredMethodElement 添加到

                                                                                   AutowiredAnnotationBeanPostProcessor#injectionMetadataCache 中。進行依賴注入管理。

 

             3.   在填充 bean 屬性之前,進行 bean 實例后處理。

                AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                      AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                            AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
                                  InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation(Object bean, String beanName)

                   默認無滿足條件的 InstantiationAwareBeanPostProcessor。

                CommonAnnotationBeanPostProcessor    無處理

                AutowiredAnnotationBeanPostProcessor   無處理

 

              4. 使用 InstantiationAwareBeanPostProcessor 處理器,進行bean 屬性的處理

                AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                     AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                          AbstractAutowireCapableBeanFactory#populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
                              InstantiationAwareBeanPostProcessor#postProcessProperties(PropertyValues pvs, Object bean, String beanName)

                   默認無滿足條件的 InstantiationAwareBeanPostProcessor。

                  CommonAnnotationBeanPostProcessor  注入 @WebServiceRef, @EJB 和 @Resource 修飾的字段和方法。

                  AutowiredAnnotationBeanPostProcessor    注入  @Autowired 和 @Value  修飾的字段或方法。

 

              5.  在初始化 bean 實例時,進行增強處理

                  AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                        AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                              AbstractAutowireCapableBeanFactory#initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
                                   AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
                                        BeanPostProcessor#postProcessBeforeInitialization(Object bean, String beanName)

               ApplicationContextAwareProcessor 檢查 bean 實例是否是Aware 系列接口的實現。當滿足條件時,設置相應的環境屬性。

               ApplicationListenerDetector  無處理。

               WebApplicationContextServletContextAwareProcessor  判斷是否是  ServletContextAware 和 ServletConfigAware 接口實現。是則進行相關屬性設置。

               ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor   判斷是否是 ImportAware  的實例,如果是則設置 AnnotationMetadata 屬性。

               PostProcessorRegistrationDelegate$BeanPostProcessorChecker  無處理邏輯

               ConfigurationPropertiesBindingPostProcessor  檢查 bean 是由 @ConfigurationProperties 注解修飾。如果是,則使用 ConfigurationPropertiesBinder#bind(ConfigurationPropertiesBean) 處理。

               CommonAnnotationBeanPostProcessor    獲取當前 bean 的 LifecycleMetadata 實例,回調  @PostConstruct 標記的方法。

               AutowiredAnnotationBeanPostProcessor   無處理。

               ErrorPageRegistrarBeanPostProcessor     當bean 是否是 ErrorPageRegistry 實現類時,則進行依次調用 ErrorPageRegistrar#registerErrorPages() 接口。

 

               6.   在完成初始化 bean 實例后,進行增強處理

                     AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                           AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
                                 AbstractAutowireCapableBeanFactory#initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
                                      AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
                                            BeanPostProcessor#postProcessAfterInitialization(Object bean, String beanName)

             ApplicationContextAwareProcessor  無處理。

            ApplicationListenerDetector  判斷是否是 ApplicationListener 的實例,並且是單例模式。如果是,則添加到 監聽器(ApplicationListener)列表中。

            WebApplicationContextServletContextAwareProcessor   無處理

            PostProcessorRegistrationDelegate$BeanPostProcessorChecker  檢查  BeanPostProcessor 數量。

            ConfigurationPropertiesBindingPostProcessor   無處理

            CommonAnnotationBeanPostProcessor     無處理

            AutowiredAnnotationBeanPostProcessor    無處理

           MethodValidationPostProcessor  檢查當前 bean 是否動態代理相關的邏輯。1.當是實現 Advised 接口,則直接返回。2.檢查是否配置了AOP增強處理(例如:@Validated ),則生成bean 的動態代理實例。

           AsyncAnnotationBeanPostProcessor

           WebServerFactoryCustomizerBeanPostProcessor   無處理

 

 

 ApplicationContextAwareProcessor,
 WebApplicationContextServletContextAwareProcessor,
 ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor,
 PostProcessorRegistrationDelegate$BeanPostProcessorChecker,
ConfigurationPropertiesBindingPostProcessor(proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false)
 WebServerFactoryCustomizerBeanPostProcessor,
 ErrorPageRegistrarBeanPostProcessor,
 CommonAnnotationBeanPostProcessor,
 AutowiredAnnotationBeanPostProcessor,
 ApplicationListenerDetector
MethodValidationPostProcessor

五. Springboot 讀取加載 自動裝置配置信息

      主要在啟動時,讀取所有jar文件中META-INF/spring.factories配置的 org.springframework.boot.autoconfigure.EnableAutoConfiguration 裝載類

org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
    org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions(ConfigurableListableBeanFactory beanFactory)
        org.springframework.context.annotation.ConfigurationClassParser#parse(Set<BeanDefinitionHolder>)
             org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorHandler#process()
                  org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGroupingHandler#processGroupImports()
                      org.springframework.context.annotation.ConfigurationClassParser.DeferredImportSelectorGrouping#getImports()
                          org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process()
                              org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry(AnnotationMetadata annotationMetadata)
                                   org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)
                                          org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getSpringFactoriesLoaderFactoryClass()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM