Spring IOC容器初始化(SpringBoot)

1. 一些疑問(wèn)

  1. @Component,@Service,@Controller,@Repository@Bean等注解怎么實(shí)現(xiàn)的?
  2. @Autowired,@Resource 是怎么自動(dòng)裝配的?
  3. @ComponentScan 為什么就可以掃描注冊(cè)Bean

2. IOC 容器 示意圖

Spring IOC :

  1. Bean定義的定位,Bean 可能定義在XML中,或者一個(gè)注解,或者其他形式。這些都被用Resource來(lái)定位, 讀取Resource獲取BeanDefinition 注冊(cè)到 Bean定義注冊(cè)表中。
  2. 第一次向容器getBean操作會(huì)觸發(fā)Bean的創(chuàng)建過(guò)程,實(shí)列化一個(gè)Bean時(shí) ,根據(jù)BeanDefinition中類信息等實(shí)列化Bean.
  3. 將實(shí)列化的Bean放到單列Bean緩存內(nèi)。
  4. 此后再次獲取向容器getBean就會(huì)從緩存中獲取。
IOC示意圖.png

3. 容器的refresh方法

方法定義在AbstractApplicationContext 中,

public void refresh() throws BeansException, IllegalStateException {
//同步代碼塊 。
        synchronized (this.startupShutdownMonitor) {
            // 準(zhǔn)備刷新.
            prepareRefresh();
            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);
            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);
                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);
                // Initialize message source for this context.
                initMessageSource();
                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();
                // Initialize other special beans in specific context subclasses.
                onRefresh();
                // Check for listener beans and register them.
                registerListeners();
                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);
                // Last step: publish corresponding event.
                finishRefresh();
            }
            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();
                // Reset 'active' flag.
                cancelRefresh(ex);
                // Propagate exception to caller.
                throw ex;
            }
            finally {
                // Reset common introspection caches in Spring's core, since we
                // might not ever need metadata for singleton beans anymore...
                resetCommonCaches();
            }
        }

prepareRefresh 準(zhǔn)備刷新

  1. 設(shè)置啟動(dòng)時(shí)間,設(shè)計(jì)容器激活標(biāo)志(active=true)
  2. 初始化 properties 資源
  3. 驗(yàn)證必須存在的properties(validateRequiredProperties)
  4. 初始earlyApplicationEnvents.用于收集已經(jīng)產(chǎn)生的ApplicationEnvents.

obtainFreshBeanFactory 獲取容器

  1. 調(diào)用子類的refeshBeanFactory(),SpringBoot中采用默認(rèn)的實(shí)現(xiàn),設(shè)置BeanFactory的SerializationId,設(shè)置refreshed標(biāo)志為true。
  2. 獲取BeanFactory
  3. XmlWebApplicationContext ,AnnotationConfigApplicationContext 會(huì)在這一步加載BeanDefinition

prepareBeanFactory 為了接下來(lái)使用BeanFactory 做準(zhǔn)備

為BeanFactory 做些標(biāo)準(zhǔn)的設(shè)置

  1. 為內(nèi)部的BeanFactory設(shè)置類加載器

  2. 設(shè)置表達(dá)式解析器,屬性編輯器。

  3. 注冊(cè)BeanPostProcessor(ApplicationContextAwareProcessor,ApplicationListenerDetector),

    • ApplicationContextAwareProcessor:對(duì)Spring 中各種Aware接口的支持,在初始化Bean前,調(diào)用Bean實(shí)現(xiàn)的Aware接口方法。
    • ApplicationListenerDetector:用于收集實(shí)現(xiàn)了ApplicationListener接口的Bean
  4. 注冊(cè)指定的依賴類型和對(duì)應(yīng)的value,

    • 例如:beanFactory.registerResolvableDependency(ResourceLoader.class, this);那么在類中自動(dòng)注入ResourceLoader類型的對(duì)象,就會(huì)拿到當(dāng)前IOC容器。
  5. 注入一些其它信息的bean,比如environment、systemProperties等

postProcessBeanFactory 后處理BeanFactory

用于在BeanFactory 完成標(biāo)準(zhǔn)的初始化之后修改BeanFactory。不同容器根據(jù)自己的需求添加特殊的后置處理器,
EmbeddedWebApplicationContext 容器在這里添加了對(duì)ServletContextAware支持的Bean后置處理器(WebApplicationContextServletContextAwareProcessor)。

invokeBeanFactoryPostProcessors 執(zhí)行BeanFactory后置處理器。

實(shí)例化并且執(zhí)行所有已經(jīng)注冊(cè)到BeanFactory中的 BeanFactoryPostProcessor。支持按照Order排序。

  1. 執(zhí)行邏輯
    調(diào)用PostProcessorRegistrationDelegate的靜態(tài)方法invokeBeanFactoryPostProcessors,
    執(zhí)行順序:
1.執(zhí)行ApplicationContext初始化器注冊(cè)的BeanDefinitionRegistryPostProcessor類型的處理器
2.執(zhí)行實(shí)現(xiàn)了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor。
3.執(zhí)行實(shí)現(xiàn)了Ordered的BeanDefinitionRegistryPostProcessor
4.執(zhí)行 所有后置處理器的 BeanFactoryPostProcessor 的接口方法
5.獲取所有的BeanFactoryPostProcessor,排除已經(jīng)執(zhí)行過(guò)得后置處理器。
6.按照2-4的順序 執(zhí)行所有未執(zhí)行的BeanFactoryPostProcessor。
  1. 介紹BeanFactoryPostProcessor 接口
針對(duì)BeanFactory 的處理,允許使用者修改容器中的bean definitions,例如:
ServletComponentRegisteringPostProcessor提供對(duì)@WebFilter,@WebServlet,@WebListener注解的掃描,并注冊(cè)到容器中。
ConfigurationClassPostProcessor 對(duì)所有的@Configuration類進(jìn)行動(dòng)態(tài)代理的增強(qiáng)。
注意使用時(shí)不能對(duì)任何BeanDefinition 進(jìn)行實(shí)列化操作。
  1. 介紹BeanDefinitionRegistryPostProcessor 接口
繼承自BeanFactoryPostProcessor,針對(duì)BeanDefinitionRegistry的后置處理器,會(huì)先于BeanFactoryPostProcessor 執(zhí)行。
  1. ConfigurationClassPostProcessor

ConfigurationClassPostProcessor后置處理器 實(shí)現(xiàn)了 PriorityOrdered接口,優(yōu)先級(jí)最高的后置處理器,在SpringBoot自動(dòng)配置的實(shí)現(xiàn)中起到舉足輕重的作用。是自動(dòng)配置功能的驅(qū)動(dòng)著,如果沒(méi)有他那些神奇的自動(dòng)配置注解都不在起作用,對(duì)@Configuration,@Bean,@ComponentScan,@Import,@ImportResource,@PropertySource注解解析。


1. 處理PropertySources 注解
加載property資源
2. 處理ComponentScans和ComponentScan注解
掃描指定包下所有@Component注解。包括@Service,@Controller,@Repository,@Configuration,@ManagedBean
3. 處理@Import注解類

解析所有包含@Import注解。spring中@Enable****注解的實(shí)現(xiàn)依賴。@Import的value 有兩種類型的Class.
3.1 ImportSelector 導(dǎo)入選擇器。
執(zhí)行非DeferredImportSelector接口的,收集配置類。
收集DeferredImportSelector接口的實(shí)現(xiàn)。稍后執(zhí)行。
3.2 ImportBeanDefinitionRegistrar 導(dǎo)入類定義注冊(cè)者
收集ImportBeanDefinitionRegistrar對(duì)象。
3.3 如果不是上面兩種類型 就會(huì)被當(dāng)作普通的configuration 類 注冊(cè)到容器。
例如@EnableScheduling
4. 處理ImportResource注解
收集@ImportResource中指定的配置文件信息。
5. 收集@Bean注解的方法

6. 處理接口默認(rèn)方法
7. 處理父類
父類className 不是"java"開頭,并且是未處理過(guò)的類型。獲取父類循環(huán)1-7。
8. 處理3.1中收集的DeferredImportSelector。
9.利用ConfigurationClassBeanDefinitionReader 處理每個(gè)Configuration類的@Bean和第4步收集的資源和3.2中收集的注冊(cè)者。

registerBeanPostProcessors 注冊(cè)bean后置處理器

  1. 委托給PostProcessorRegistrationDelegate的靜態(tài)方法registerBeanPostProcessors執(zhí)行

    1.1 按照 PriorityOrdered,Ordered,普通,MergedBeanDefinitionPostProcessor 添加到 beanFactory 的beanPostProcessors屬性中。最后添加ApplicationListenerDetector。

  2. BeanPostProcessors 接口
    該接口在Bean的實(shí)列話過(guò)程中被調(diào)用,在對(duì)一個(gè)對(duì)象進(jìn)行初始化 前后 被調(diào)用。

例如:實(shí)現(xiàn)了 EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationContextAware等Aware就是這個(gè)時(shí)候 被執(zhí)行的。

  1. MergedBeanDefinitionPostProcessor 接口

? 該接口繼承了BeanPostProcessors接口, 會(huì)在 bean 實(shí)列化 之后 屬性注入前 執(zhí)行。例如 對(duì)@Autowired @Resource @Value 注解的解析。

initMessageSource

在Spring容器中初始化一些國(guó)際化相關(guān)的屬性。

initApplicationEventMulticaster

在容器中初始化Application事件廣播器。

onRefresh

onRefresh是一個(gè)模板方法,留給子類容器擴(kuò)贊,不同的容器做不同的事情。

例如:容器AnnotationConfigEmbeddedWebApplicationContext中會(huì)調(diào)用createEmbeddedServletContainer方法去創(chuàng)建內(nèi)置的Servlet容器。
EmbeddedServletContainerAutoConfiguration 類中定義了 Spring boot 支持的三種 Servlet容器。
目前SpringBoot只支持3種內(nèi)置的Servlet容器:

  1. Tomcat
  2. Jetty
  3. Undertow

registerListeners

  1. 將所有的 ApplicationListener 實(shí)現(xiàn)類注冊(cè) 到 ApplicationEventMulticaster中,覺(jué)得是觀察者模式。
  2. 把已經(jīng)產(chǎn)生的事件廣播出去。

finishBeanFactoryInitialization

實(shí)列化所有 非懶加載的 類。

finishRefresh

  1. 完成容器的初始化過(guò)程,發(fā)布相應(yīng)事件。
  2. 啟動(dòng)容器的聲明周期處理器。管理容器聲明周期。
  3. 發(fā)布 ContextRefreshedEvent事件。
  4. 啟動(dòng)內(nèi)嵌的Servlet容器。
  5. 發(fā)布容器啟動(dòng)事件。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容