国产在线97色永久免费视频_91青青草原国产免费播放_久久久久久久岛国免费_亚洲中文久久精品无码照片_中文字幕高清无码男人的天堂

環(huán)球今頭條!【Spring源碼】- 02 Spring IoC容器啟動(dòng)之refresh方法

2023-03-28 15:25:43    來(lái)源:騰訊云    

register

AnnotationConfigApplicationContext構(gòu)造方法中三個(gè)方法中第一個(gè)方法上面分析過(guò)了,現(xiàn)在我們來(lái)看下第二個(gè)方法:register(componentClasses)

之前使用XML方式:new ClassPathXmlApplicationContext("classpath:spring.xml");,構(gòu)造方法中需要指定xml配置文件路徑,然后就可以解析xml文件中、等配置進(jìn)行IoC啟動(dòng)初始化。同理,使用注解方式也需要給Context指定一個(gè)起始配置源頭,使用配置類代替xml配置文件,然后根據(jù)這個(gè)起始配置類一步步的解析下去。


(相關(guān)資料圖)

@Configuration@ComponentScan(basePackageClasses = {TestConfig.class})@Import(TestService03.class)public class TestConfig { @Bean public TestService01 testService01(){  return new TestService01(); }}

通過(guò)這個(gè)配置類,Spring就可以解析@ComponentScan、@Import@Bean等這些注解,實(shí)現(xiàn)Bean注入到IoC容器中。@Configuration注解定義的配置類就相當(dāng)于之前xml配置文件,不過(guò)由于現(xiàn)在Spring主流都推薦注解方式,xml方案使用的概率會(huì)越來(lái)越低。

跟蹤register(componentClasses)方法,核心邏輯在:AnnotatedBeanDefinitionReader#doRegisterBean

private  void doRegisterBean(Class beanClass, @Nullable String name,   @Nullable Class[] qualifiers, @Nullable Supplier supplier,   @Nullable BeanDefinitionCustomizer[] customizers) {  //先把此實(shí)體類型轉(zhuǎn)換為一個(gè)BeanDefinition  AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);  /**   * abd.getMetadata()元數(shù)據(jù)包括注解信息、是否內(nèi)部類、類Class基本信息等等   * 此處由conditionEvaluator#shouldSkip去過(guò)濾,此Class是否是配置類   * 大體邏輯為:必須有@Configuration修飾,然后解析一些Condition注解,看是否排除~   */  if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {   return;  }  abd.setInstanceSupplier(supplier);  // 解析Scope  ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);  abd.setScope(scopeMetadata.getScopeName());  // 得到Bean的名稱 一般為首字母小寫(xiě)(此處為AnnotationBeanNameGenerator)  String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));  // 設(shè)定一些注解默認(rèn)值,如lazy、Primary等等  AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);  if (qualifiers != null) {// 解析qualifiers,若有此注解  則primary都成為true了   for (Class qualifier : qualifiers) {    if (Primary.class == qualifier) {     abd.setPrimary(true);    }    else if (Lazy.class == qualifier) {     abd.setLazyInit(true);    }    else {     abd.addQualifier(new AutowireCandidateQualifier(qualifier));    }   }  }  if (customizers != null) {// 自定義定制信息(一般都不需要)   for (BeanDefinitionCustomizer customizer : customizers) {    customizer.customize(abd);   }  }  // 下面解析Scope是否需要代理,最后把這個(gè)Bean注冊(cè)進(jìn)去  BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);  definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);  BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);}

就是將傳入的配置類解析成解析成BeanDefinition,注冊(cè)到IoC容器中,后續(xù)ConfigurationClassPostProcessor這個(gè)BeanFactory后置處理器在IoC開(kāi)始真正初始化時(shí),可以獲取到這些配置類的BeanDefinition集合,啟動(dòng)解析。

refresh

前面分析了AnnotationConfigApplicationContext構(gòu)造方法中前兩個(gè),這兩個(gè)方法基本都是IoC啟動(dòng)的前戲:為IoC容器的啟動(dòng)做熱身準(zhǔn)備;真正的IoC容器啟動(dòng)初始化流程是在refresh()方法中,這是了解IoC容器啟動(dòng)流程最關(guān)鍵、核心的一個(gè)方法。

refresh方法定義在AbstractApplicationContext,采用模板模式,定義好IoC啟動(dòng)的流程以及每個(gè)步驟的作用,并提供基礎(chǔ)實(shí)現(xiàn),其它子類可以重寫(xiě)進(jìn)行擴(kuò)展。

public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {  //Context進(jìn)行刷新前的準(zhǔn)備工作  prepareRefresh();  // 創(chuàng)建并初始化 BeanFactory,這步會(huì)將BeanDefinition載入到BeanFactory中  ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  /**  * 填充BeanFactory功能  * 上面獲取獲取的 BeanFactory其實(shí)還不能投入生產(chǎn),因?yàn)檫€少配置了一些東西,比如 context的 ClassLoader 和 后置處理器等等。  */  prepareBeanFactory(beanFactory);  try {   /**   * 默認(rèn)空實(shí)現(xiàn),留給子類擴(kuò)展使用   * 可以參照:AbstractRefreshableWebApplicationContext#postProcessBeanFactory()   */   postProcessBeanFactory(beanFactory);   /**   * 調(diào)用BeanFactory后置處理器(包括BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor)   */   invokeBeanFactoryPostProcessors(beanFactory);   registerBeanPostProcessors(beanFactory);   //初始化消息源   initMessageSource();   //初始化應(yīng)用上下文事件廣播器   initApplicationEventMulticaster();   //初始化其它特殊的Bean,由具體子類實(shí)現(xiàn)   onRefresh();   //注冊(cè)事件監(jiān)聽(tīng)器   registerListeners();   //初始化所有單實(shí)例Bean,使用懶加載模式的Bean除外   finishBeanFactoryInitialization(beanFactory);   //完成刷新并發(fā)布容器刷新事件   finishRefresh();  }  catch (BeansException ex) {   ...//省略  }  finally {   resetCommonCaches();  } }}

下面就來(lái)分析下每個(gè)方法作用,以了解IoC容器的啟動(dòng)流程。

prepareRefresh

prepareRefresh從方法名稱可以看出,該方法主要在refresh執(zhí)行前進(jìn)行一些簡(jiǎn)單的準(zhǔn)備工作,如設(shè)置Context的啟動(dòng)時(shí)間、狀態(tài),以及系統(tǒng)屬性相關(guān)擴(kuò)展。

/**  * 初始化上下文環(huán)境,對(duì)系統(tǒng)的環(huán)境變量或者系統(tǒng)屬性進(jìn)行準(zhǔn)備和校驗(yàn),如環(huán)境變量中必須設(shè)置某個(gè)值才能運(yùn)行,否則不能運(yùn)行,這個(gè)時(shí)候可以在這里加這個(gè)校驗(yàn),重寫(xiě)initPropertySources方法就好了  *  * 該方法主要是做一些準(zhǔn)備工作,如:  *  1、設(shè)置 context 啟動(dòng)時(shí)間  *  2、設(shè)置 context 的當(dāng)前狀態(tài)  *  3、初始化 context environment 中占位符  *  4、對(duì)屬性進(jìn)行必要的驗(yàn)證  */ protected void prepareRefresh() {  //設(shè)置啟動(dòng)時(shí)間  this.startupDate = System.currentTimeMillis();  //設(shè)置context當(dāng)前狀態(tài)  this.closed.set(false);//標(biāo)志context狀態(tài):未關(guān)閉  this.active.set(true);//標(biāo)志context狀態(tài):活躍中  /**   * 初始化context environment(上下文環(huán)境)中屬性源信息,默認(rèn)這里是空實(shí)現(xiàn),什么都沒(méi)做,這里主要提供給子類擴(kuò)展,采用模板設(shè)計(jì)模式   * 比如非web環(huán)境下,context environment是StandardEnvironment類型,只會(huì)在創(chuàng)建時(shí)初始化兩類屬性源:systemEnvironment(系統(tǒng)環(huán)境變量)   * 和systemProperties(應(yīng)用環(huán)境變量),通過(guò)@PropertySource注解等方式配置這時(shí)是還沒(méi)有加載的   *   *   * 該方法主要有兩個(gè)常見(jiàn)擴(kuò)展:   *  1、可以在該類中擴(kuò)展PropertySource來(lái)源,如:getEnvironment().getPropertySources().addXXX(PropertySource ps),可以參見(jiàn)GenericWebApplicationContext#initPropertySources()   *  2、可以在方法中添加必要屬性驗(yàn)證,一些屬性對(duì)于應(yīng)用來(lái)說(shuō)是必要的,缺失則會(huì)影響系統(tǒng)的正常邏輯,   *   如:getEnvironment().setRequiredProperties("DB_IP"),下一步就會(huì)從context environment上驗(yàn)證是否存在該屬性,如果沒(méi)有則會(huì)拋出異常并退出Spring應(yīng)用   */  initPropertySources();  /**   * 對(duì)屬性必要性進(jìn)行校驗(yàn),邏輯參見(jiàn):AbstractPropertyResolver#validateRequiredProperties   */  getEnvironment().validateRequiredProperties();  //早期事件監(jiān)聽(tīng)器集合如果為空,就新建一個(gè);如果不為空,就先清空事件監(jiān)聽(tīng)器集合,然后將早期事件監(jiān)聽(tīng)器整體放入事件監(jiān)聽(tīng)器集合。  if (this.earlyApplicationListeners == null) {   //默認(rèn)情況下,earlyApplicationListeners為null   this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);  }  else {   this.applicationListeners.clear();   this.applicationListeners.addAll(this.earlyApplicationListeners);  }  //保存容器中的一些早期事件,待事件派發(fā)器multicaster初始化完成后進(jìn)行事件發(fā)布  this.earlyApplicationEvents = new LinkedHashSet<>();}

這里主要注意下initPropertySources()getEnvironment().validateRequiredProperties()這兩句代碼。PropertySourceSpring中代表一組變量,即類似對(duì)應(yīng)于一個(gè)配置文件,比如@PropertySource("test01.properties")這個(gè)常用的注解就是將配置文件解析成一個(gè)PropertySource對(duì)象。

initPropertySources()方法主要用于擴(kuò)展配置來(lái)源,比如可以從網(wǎng)絡(luò)、物理文件、數(shù)據(jù)庫(kù)等加載配置信息。StandardEnvironment在創(chuàng)建時(shí),會(huì)自動(dòng)將系統(tǒng)變量System.getProperties()和應(yīng)用變量System.getenv()加載進(jìn)來(lái),所以initPropertySources默認(rèn)只提供的是空實(shí)現(xiàn),主要用于子類擴(kuò)展使用。

initPropertySources方法主要有兩個(gè)常見(jiàn)擴(kuò)展場(chǎng)景:

1、可以在該類中擴(kuò)展PropertySource來(lái)源,如:getEnvironment().getPropertySources().addXXX(PropertySource ps),可以參見(jiàn)GenericWebApplicationContext#initPropertySources()2、可以在方法中添加必要屬性驗(yàn)證,一些屬性對(duì)于應(yīng)用來(lái)說(shuō)是必要的,缺失則會(huì)影響系統(tǒng)的正常邏輯,如:getEnvironment().setRequiredProperties("DB_IP"),下一步就會(huì)從context environment上驗(yàn)證是否存在該屬性,如果沒(méi)有則會(huì)拋出異常并退出Spring應(yīng)用

getEnvironment().validateRequiredProperties()這句主要是對(duì)setRequiredProperties()方法設(shè)置的屬性進(jìn)行必要性檢查,如果某個(gè)必要屬性環(huán)境中不存在,則拋出異常退出應(yīng)用。

obtainFreshBeanFactory

BeanFactory才是Spring中基本的IoC容器,ApplicationContext其實(shí)內(nèi)部包裝了一個(gè)BeanFactory,并對(duì)其進(jìn)行了增強(qiáng),使其更智能、更好用。ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();這句主要意思是:通知Context,我要開(kāi)始使用IoC容器進(jìn)行初始化工作了,請(qǐng)?zhí)峁┙o我一個(gè)BeanFactory容器。這個(gè)方法比較簡(jiǎn)單,基本沒(méi)有需要擴(kuò)展的,就不再仔細(xì)研究。

prepareBeanFactory

上面獲取獲取的BeanFactory容器其實(shí)還不能投入生產(chǎn),因?yàn)檫€缺少一些配置信息,這里主要向BeanFactory填充一些必要的配置。

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { // 設(shè)置beanFactory的classLoader beanFactory.setBeanClassLoader(getClassLoader()); // 設(shè)置beanFactory的表達(dá)式語(yǔ)言處理器,Spring3開(kāi)始增加了對(duì)語(yǔ)言表達(dá)式的支持,默認(rèn)可以使用#{bean.xxx}的形式來(lái)調(diào)用相關(guān)屬性值 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); // 為beanFactory增加一個(gè)默認(rèn)的propertyEditor beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); // 添加一個(gè)ApplicationContextAwareProcessor類型的Bean后置處理器,該后置處理器用于處理*Aware接口的依賴注入 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); /** * 自動(dòng)裝配時(shí)如下接口中setter方法的依賴注入會(huì)被忽略 * 如:EnvironmentAware#setEnvironment()該setter不能用于自動(dòng)裝配時(shí)依賴注入方法, * 因?yàn)檫@些*Aware接口統(tǒng)一采用ApplicationContextAwareProcessor這個(gè)Bean后置處理器進(jìn)行依賴注入 */ beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); /** * 設(shè)置幾個(gè)自動(dòng)裝配的特殊規(guī)則 * DefaultListableBeanFactory#findAutowireCandidates(DependencyDescriptor ds)在查找依賴注入值時(shí): *  1、首先會(huì)從resolvableDependencies容器中查找,如果有直接返回找到的bean進(jìn)行依賴注入; *  2、如果沒(méi)有,再?gòu)腎oC容器中查找 * 所以,resolvableDependencies容器可以看成對(duì)常規(guī)IoC的一種擴(kuò)充 */ beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); /** * 添加一個(gè)ApplicationListenerDetector類型的Bean后置處理器,將類型是ApplicationListener的bean添加到事件廣播器,以便觸發(fā)事件時(shí)被調(diào)用 */ beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); /** * 增加對(duì)AspectJ的支持 * 檢查容器中是否包含名稱為loadTimeWeaver的bean,實(shí)際上是增加Aspectj的支持 *     AspectJ采用編譯期織入、類加載期織入兩種方式進(jìn)行切面的織入 *     類加載期織入簡(jiǎn)稱為L(zhǎng)TW(Load Time Weaving),通過(guò)特殊的類加載器來(lái)代理JVM默認(rèn)的類加載器實(shí)現(xiàn) */ if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {  // 添加BEAN后置處理器:LoadTimeWeaverAwareProcessor  // 在BEAN初始化之前檢查BEAN是否實(shí)現(xiàn)了LoadTimeWeaverAware接口,  // 如果是,則進(jìn)行加載時(shí)織入,即靜態(tài)代理。  beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));  beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } // 注冊(cè)默認(rèn)的系統(tǒng)環(huán)境bean    // 這樣應(yīng)用程序中通過(guò):getBean("environment")、getBean("systemProperties")、getBean("systemEnvironment") if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {  beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {  beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {  beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); }}

上面邏輯大致可以總結(jié):

BeanFactory設(shè)置ClassLoaderEL表達(dá)式解析器等;添加一個(gè)BeanPostProcessorApplicationContextAwareProcessor,這個(gè)主要完成對(duì)*Aware接口功能支持,實(shí)現(xiàn)的核心邏輯見(jiàn)下:判斷是否實(shí)現(xiàn)了XXXAware接口,如果實(shí)現(xiàn)則調(diào)用對(duì)應(yīng)的setter方法注入依賴值。
private void invokeAwareInterfaces(Object bean) { if (bean instanceof EnvironmentAware) {  ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) {  ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver); } if (bean instanceof ResourceLoaderAware) {  ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) {  ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) {  ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) {  ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); }}
ignoreDependencyInterface方法設(shè)置一些忽略接口:自動(dòng)裝配時(shí)如遇到忽略接口中setter方法的依賴注入會(huì)被忽略,因?yàn)檫@些*Aware接口統(tǒng)一采用ApplicationContextAwareProcessor這個(gè)后置處理器進(jìn)行依賴注入。registerResolvableDependency方法設(shè)置一些特殊的內(nèi)置對(duì)象,DefaultListableBeanFactory#findAutowireCandidates(DependencyDescriptor ds)在查找依賴注入值時(shí):a、首先會(huì)從resolvableDependencies容器中查找,如果有直接返回找到的bean進(jìn)行依賴注入;b、如果沒(méi)有,再?gòu)?code>IoC容器中查找。因此,resolvableDependencies容器可以看出是對(duì)IoC容器的一種擴(kuò)充,該容器中的對(duì)象是沒(méi)有經(jīng)過(guò)Spring一系列容器創(chuàng)建流程,而是直接new方式創(chuàng)建。再添加一個(gè)Bean后置處理器:ApplicationListenerDetector,將系統(tǒng)中實(shí)現(xiàn)ApplicationListener接口的對(duì)象都統(tǒng)一存儲(chǔ)到Set> applicationListeners中,采用了典型的事件監(jiān)聽(tīng)/發(fā)布模式;LTW功能判斷,LTW全稱LoadTimeWeaver,即:加載時(shí)織入。AOPOOP一樣,是一種編程思想,按照織入時(shí)機(jī)可以分為三類:編譯時(shí)織入、類加載時(shí)織入和運(yùn)行時(shí)織入。AspectJ實(shí)現(xiàn)就是編譯時(shí)織入,采用的是一種特殊的編譯器;Spring AOP采用的動(dòng)態(tài)代理實(shí)現(xiàn)(jdk動(dòng)態(tài)代理、cglib動(dòng)態(tài)代理),這是一種運(yùn)行時(shí)織入,缺點(diǎn)就是必須納入IoC管理的Bean才能被代理;而LTW是類加載時(shí)織入,借助于JVM提供的Instrumentation技術(shù),在JDK加載類時(shí)織入增強(qiáng)邏輯。

Instrumentation是在JVM加載Class時(shí)進(jìn)行代碼織入,對(duì)現(xiàn)有應(yīng)用沒(méi)有任何的侵入,APM Agent開(kāi)發(fā)中就比較常用該技術(shù)。

注冊(cè)三個(gè)環(huán)境變量相關(guān)Bean到容器中,這樣應(yīng)用中可以依賴注入到程序中進(jìn)行使用;beanFactory.registerSingleton方式把對(duì)象存儲(chǔ)到singletonObjects集合中,它類似于一個(gè)緩存,從IoC獲取Bean時(shí),首先會(huì)通過(guò)getSingleton方法從緩存拿,如果緩存拿不到再去獲取對(duì)應(yīng)的BeanDefinition進(jìn)行實(shí)例化,然后實(shí)例化對(duì)象放到singletonObjects集合中。

postProcessBeanFactory

postProcessBeanFactory(beanFactory)默認(rèn)是空實(shí)現(xiàn),主要是留給子類進(jìn)行擴(kuò)展,從名稱上看該方法主要用于添加BeanFactoryPostProcessor,AnnotationConfigApplicationContext已經(jīng)在前面注冊(cè)了一個(gè)ConfigurationClassPostProcessor,主要用于完成對(duì)Spring配置類的處理,其它子類可以重新這個(gè)方法增加其它BeanFactoryPostProcessor對(duì)象,實(shí)現(xiàn)功能擴(kuò)充。

invokeBeanFactoryPostProcessors

前面巴拉巴拉一大堆,基本還是各種配置、填充工作,這一步就到了IoC容器開(kāi)始真正干活的階段了。invokeBeanFactoryPostProcessors(beanFactory)方法主要就是完成對(duì)所有注冊(cè)進(jìn)來(lái)的BeanFactory后置處理器執(zhí)行調(diào)用,包括BeanFactoryPostProcessor及其子類BeanDefinitionRegistryPostProcessor。這里就會(huì)有個(gè)前面提到的Spring中非常重要的一個(gè)類:ConfigurationClassPostProcessor開(kāi)始被執(zhí)行,它執(zhí)行完成后,所有需要Spring管理的Bean都會(huì)被解析成BeanDefinition注冊(cè)進(jìn)來(lái)。由于ConfigurationClassPostProcessor非常的復(fù)雜,后續(xù)會(huì)單獨(dú)分析這個(gè)類,這篇主要是對(duì)IoC啟動(dòng)的流程有個(gè)大致的、直觀印象。執(zhí)行完這步,你只需要簡(jiǎn)單知道@Configuration、@Bean、@Import@ComponentScan@Component等等相關(guān)配置注解會(huì)被處理,相關(guān)的Bean也被解析成BeanDefinition注冊(cè)進(jìn)來(lái)即可。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); // LTW探測(cè) if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {  beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));  beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}

getBeanFactoryPostProcessors()獲取到ApplicationContext.beanFactoryPostProcessors集合中存儲(chǔ)的BeanFactoryPostProcessor,通過(guò)addBeanFactoryPostProcessor()方法添加的,這里集合為空,因?yàn)閺那懊娲a看并沒(méi)有調(diào)用過(guò)該方法。

這里核心在invokeBeanFactoryPostProcessors()方法。首先,看下if (beanFactory instanceof BeanDefinitionRegistry)判斷,如果容器不是BeanDefinitionRegistry類型或子類,則表示當(dāng)前容器不能向容器注冊(cè)Bean,所以只需要執(zhí)行BeanFactoryPostProcessor類型后置處理器即可,BeanDefinitionRegistryPostProcessor后置處理器不需要執(zhí)行,因?yàn)樵摵笾锰幚砥髦饕怯脕?lái)向IoC容器中注冊(cè)Bean,大部分我們使用的容器都是BeanDefinitionRegistry類型,這樣才能把我們業(yè)務(wù)Bean納入Spring管理,所以基本上都是走if語(yǔ)句塊

//判斷我們的beanFactory是否實(shí)現(xiàn)了BeanDefinitionRegistryif (beanFactory instanceof BeanDefinitionRegistry) { ...//省略}else { invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}

invokeBeanFactoryPostProcessors方法核心就是執(zhí)行BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessor,但是涉及到執(zhí)行優(yōu)先級(jí)、執(zhí)行后可能會(huì)產(chǎn)生新PostProcessor等,所以這里的代碼看起來(lái)比較長(zhǎng),總結(jié)下執(zhí)行邏輯大致如下:

1、先執(zhí)行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法,其中BeanDefinitionRegistryPostProcessor執(zhí)行優(yōu)先級(jí)如下:a、addBeanFactoryPostProcessor()傳入到優(yōu)先級(jí)最高,因?yàn)椴恍枰獙?shí)例化,直接可以獲取到對(duì)象進(jìn)行執(zhí)行;b、然后從IoC容器中獲取PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,實(shí)例化并排序后執(zhí)行postProcessBeanDefinitionRegistry方法c、然后從IoC容器中獲取Ordered接口的BeanDefinitionRegistryPostProcessor,實(shí)例化并排序后執(zhí)行postProcessBeanDefinitionRegistry方法d、然后從IoC容器中獲取剩余的BeanDefinitionRegistryPostProcessor,實(shí)例化后執(zhí)行postProcessBeanDefinitionRegistry方法;注意這個(gè)處理步驟存在一個(gè)循環(huán),主要是存在執(zhí)行前面的BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法時(shí),存在可能會(huì)向IoC容器中注冊(cè)新的BeanDefinitionRegistryPostProcessor,通過(guò)循環(huán)保證都會(huì)被執(zhí)行;2、然后執(zhí)行BeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法,執(zhí)行順序參照步驟1中執(zhí)行順序;3、最后才會(huì)執(zhí)行BeanFactoryPostProcessor#postProcessBeanFactory,執(zhí)行優(yōu)先級(jí)和BeanDefinitionRegistryPostProcessor一致:a、addBeanFactoryPostProcessor()傳入到優(yōu)先級(jí)最高,因?yàn)椴恍枰獙?shí)例化,直接可以獲取到對(duì)象進(jìn)行執(zhí)行;b、然后從IoC容器中獲取PriorityOrdered接口的BeanFactoryPostProcessor,實(shí)例化并排序后執(zhí)行postProcessBeanFactory方法c、然后從IoC容器中獲取Ordered接口的BeanFactoryPostProcessor,實(shí)例化并排序后執(zhí)行postProcessBeanFactory方法d、然后從IoC容器中獲取剩余的BeanFactoryPostProcessor,實(shí)例化后執(zhí)行postProcessBeanFactory方法

這里有個(gè)細(xì)節(jié),在執(zhí)行BeanFactoryPostProcessor#postProcessBeanFactory方法是沒(méi)有循環(huán),而執(zhí)行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry中存在一個(gè)循環(huán),主要是因?yàn)?code>BeanFactoryPostProcessor#postProcessBeanFactory方法是不會(huì)像IoC中注冊(cè)Bean,這樣執(zhí)行過(guò)程中就不會(huì)產(chǎn)生新的BeanFactoryPostProcessor。

上面寫(xiě)了一大堆,概況下就是:

1、方法優(yōu)先級(jí):BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry> BeanDefinitionRegistryPostProcessor#postProcessBeanFactory> BeanFactoryPostProcessor#postProcessBeanFactory;

2、同方法優(yōu)先級(jí):addBeanFactoryPostProcessor> PriorityOrdered> Ordered> 非排序

registerBeanPostProcessors

registerBeanPostProcessors方法主要是將BeanDefinition對(duì)應(yīng)的BeanPostProcessor實(shí)例化并通過(guò)beanFactory.addBeanPostProcessor()方法注冊(cè)進(jìn)來(lái)。前面分析過(guò)AnnotationConfigUtils.registerAnnotationConfigProcessors會(huì)向容器注冊(cè)幾個(gè)Spring內(nèi)置的BeanPostProcessor,這步主要是將應(yīng)用中引入的BeanPostProcessor注冊(cè)進(jìn)來(lái)。

上步invokeBeanFactoryPostProcessors執(zhí)行完成后,Spring會(huì)將所有的Bean解析成BeanDefinition注冊(cè)到容器中,其中就可能包含BeanPostProcessorBeanDefinition信息,這個(gè)方法就是把這些BeanPostProcessor對(duì)應(yīng)的BeanDefinition通過(guò)getBean方式實(shí)例化,并通過(guò)addBeanPostProcessor()注冊(cè)進(jìn)來(lái),這樣這些BeanPostProcessor才能起作用。

這個(gè)方法代碼巴拉巴拉一大堆,流出總結(jié)起來(lái)還是很清晰,這里就不再上代碼:

獲取實(shí)現(xiàn)PriorityOrdered接口的BeanPostProcessor,然后通過(guò)getBean()方法實(shí)例化,排序后注冊(cè)到容器中;獲取實(shí)現(xiàn)Ordered接口的BeanPostProcessor,然后通過(guò)getBean()方法實(shí)例化,排序后注冊(cè)到容器中;獲取常規(guī)沒(méi)有實(shí)現(xiàn)PriorityOrderedOrdered接口BeanPostProcessor,然后通過(guò)getBean()方法實(shí)例化,注冊(cè)到容器中;上述步驟中MergedBeanDefinitionPostProcessor類型會(huì)單獨(dú)存儲(chǔ)到internalPostProcessors集合中,排序后保證放到末尾;最后移除ApplicationListenerDetector重新追加到最末尾。

注意:這里有個(gè)細(xì)節(jié)就是要保證高級(jí)別優(yōu)先級(jí)的BeanPostProcessor全部實(shí)例化完成后,才可以進(jìn)行下一個(gè)優(yōu)先級(jí)類型的BeanPostProcessor,因?yàn)?code>BeanPostProcessor主要就是圍繞Bean實(shí)例化進(jìn)行擴(kuò)展,這樣就可以保證高優(yōu)先級(jí)的BeanPostProcessor可以參與到對(duì)低優(yōu)先級(jí)的BeanPostProcessor實(shí)例化過(guò)程中。

和上步invokeBeanFactoryPostProcessors不同的是,這里只是把所有的BeanPostProcessor注冊(cè)進(jìn)來(lái),并沒(méi)有去執(zhí)行,因?yàn)檫@也很好理解:BeanPostProcessor是圍繞在Bean實(shí)例化周?chē)臄U(kuò)展點(diǎn),這里服務(wù)Bean存儲(chǔ)在容器中基本都還是BeanDefinition,還沒(méi)有進(jìn)行實(shí)例化。

initMessageSource

initMessageSource方法主要是處理國(guó)際化相關(guān)工作,后臺(tái)開(kāi)發(fā)中很少涉及,這里就不展開(kāi)分析。

initApplicationEventMulticaster

initApplicationEventMulticaster是上下文環(huán)境中初始化一個(gè)事件廣播器,用于事件發(fā)布,后續(xù)分析Spring事件機(jī)制再整體分析。

onRefresh

onRefresh默認(rèn)是空實(shí)現(xiàn),模板模式設(shè)計(jì)主要用于子類擴(kuò)展??梢詤⒄?code>SpringBoot中ServletWebServerApplicationContext這個(gè)類,重寫(xiě)了onRefresh()方法,在這個(gè)方法中完成內(nèi)嵌Servlet容器的創(chuàng)建:Tomcat、Jetty、Undertow,將程序內(nèi)嵌一個(gè)Servlet容器后,就可以獨(dú)立運(yùn)行。

registerListeners

registerListeners方法主要完成事件監(jiān)聽(tīng)器注冊(cè),將實(shí)現(xiàn)了ApplicationListener接口的監(jiān)聽(tīng)器bean注冊(cè)到ApplicationEventMulticaster上,在注冊(cè)完以后,還會(huì)將其前期的事件發(fā)布給相匹配的監(jiān)聽(tīng)器。后續(xù)分析Spring事件機(jī)制再整體分析。

關(guān)鍵詞:
[責(zé)任編輯:h001]

資訊播報(bào)

聯(lián)系我們:435 226 40 @qq.com

版權(quán)所有 重播新聞網(wǎng) www.hbmingxingmzc.cn 京ICP備2022022245號(hào)-17