国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

瀏覽:2日期:2023-08-17 14:02:48

refresh()

該方法是 Spring Bean 加載的核心,它是 ClassPathXmlApplicationContext 的父類 AbstractApplicationContext 的一個(gè)方法 , 顧名思義,用于刷新整個(gè)Spring 上下文信息,定義了整個(gè) Spring 上下文加載的流程。

public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { //準(zhǔn)備刷新上下文 環(huán)境 this.prepareRefresh(); //初始化BeanFactory,并進(jìn)行XML文件讀取 /* * ClassPathXMLApplicationContext包含著B(niǎo)eanFactory所提供的一切特征,在這一步驟中將會(huì)復(fù)用 * BeanFactory中的配置文件讀取解析及其他功能,這一步之后,ClassPathXmlApplicationContext * 實(shí)際上就已經(jīng)包含了BeanFactory所提供的功能,也就是可以進(jìn)行Bean的提取等基礎(chǔ)操作了。 */ ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); //對(duì)beanFactory進(jìn)行各種功能填充 this.prepareBeanFactory(beanFactory);​ try { //子類覆蓋方法做額外處理 this.postProcessBeanFactory(beanFactory); //激活各種beanFactory處理器 this.invokeBeanFactoryPostProcessors(beanFactory); //注冊(cè)攔截Bean創(chuàng)建的Bean處理器,這里只是注冊(cè),真正的調(diào)用實(shí)在getBean時(shí)候 this.registerBeanPostProcessors(beanFactory); //為上下文初始化Message源,即不同語(yǔ)言的消息體,國(guó)際化處理 this.initMessageSource(); //初始化應(yīng)用消息廣播器,并放入“applicationEventMulticaster”bean中 this.initApplicationEventMulticaster(); //留給子類來(lái)初始化其它的Bean this.onRefresh(); //在所有注冊(cè)的bean中查找Listener bean,注冊(cè)到消息廣播器中 this.registerListeners(); //初始化剩下的單實(shí)例(非惰性的) this.finishBeanFactoryInitialization(beanFactory); //完成刷新過(guò)程,通知生命周期處理器lifecycleProcessor刷新過(guò)程,同時(shí)發(fā)出ContextRefreshEvent通知?jiǎng)e人 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(); }​ }}

每個(gè)子方法的功能之后一點(diǎn)一點(diǎn)再分析,首先 refresh()方法有幾點(diǎn)是值得我們學(xué)習(xí)的:

方法是加鎖的,這么做的原因是避免多線程同時(shí)刷新 Spring 上下文; 盡管加鎖可以看到是針對(duì)整個(gè)方法體的,但是沒(méi)有在方法前加 synchronized 關(guān)鍵字,而使用了對(duì)象鎖 startUpShutdownMonitor,這樣做有兩個(gè)好處: (1)refresh()方法和 close()方法都使用了 startUpShutdownMonitor 對(duì)象鎖加鎖,這就保證了在調(diào)用 refresh()方法的時(shí)候無(wú)法調(diào)用 close()方法,反之依然,這樣就避免了沖突。 (2)使用對(duì)象鎖可以減小同步的范圍,只對(duì)不能并發(fā)的代碼塊進(jìn)行加鎖,提高了整體代碼運(yùn)行的速率。 在 refresh()方法中整合了很多個(gè)子方法,使得整個(gè)方法流程清晰易懂。這樣一來(lái),方便代碼的可讀性和可維護(hù)性。

3.1 prepareRefresh方法

//設(shè)置啟動(dòng)時(shí)間,是否激活標(biāo)識(shí)位,初始化屬性源(property source)配置protected void prepareRefresh() { this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); if (this.logger.isDebugEnabled()) { if (this.logger.isTraceEnabled()) { this.logger.trace('Refreshing ' + this); } else { this.logger.debug('Refreshing ' + this.getDisplayName()); } }​ // 在上下文環(huán)境中初始化任何占位符屬性源。(空的方法,留給子類覆蓋) this.initPropertySources(); //驗(yàn)證所有的必需的屬性是否可解析,若無(wú)則不能解析并拋出異常 this.getEnvironment().validateRequiredProperties(); if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet(this.applicationListeners); } else { this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); }​ this.earlyApplicationEvents = new LinkedHashSet();}

prepareRefresh 的內(nèi)容如上,該方法主要進(jìn)行環(huán)境的準(zhǔn)備,包括 Context 的啟動(dòng)時(shí)間,活動(dòng)狀態(tài),然后設(shè)置 context 中的配置數(shù)據(jù)源,使用默認(rèn)的 StandardEnvironment 對(duì)象,該對(duì)象添加了 System.env()屬性和 System.properties()屬性 。 initPropertySources 方法用于初始化 context 中 environment 的屬性源。在 AbstractApplicationContext 中為空實(shí)現(xiàn)。其他子類的實(shí)現(xiàn)如下:

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

在子類 GenericWebApplicationContext 和 AbstractRefreshableWebApplicationContext 的實(shí)現(xiàn)大致一致,都是:

protected void initPropertySources() { ConfigurableEnvironment env = this.getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, this.servletConfig); }​}

通過(guò)在 getEnvironment 方法中,重寫 createEnvironment 方法 。

protected ConfigurableEnvironment createEnvironment() { return new StandardServletEnvironment();}

將 AbstractApplicationContext 類中默認(rèn)的 StandardEnvironment 替換為StandardServletEnvironment, StandardServletEnvironment 的關(guān)系圖為:

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

因而會(huì)執(zhí)行 StandardServletEnvironment 類的 initPropertySources 方法,為 context 添加 ServletContext 和 ServletConfig 對(duì)應(yīng)的配置屬性源。

public void initPropertySources(@Nullable ServletContext servletContext, @Nullable ServletConfig servletConfig) { WebApplicationContextUtils.initServletPropertySources(this.getPropertySources(), servletContext, servletConfig);}

接著是分析 this.getEnvironment().validateRequiredProperties()方法,在上述我們已經(jīng)提到 getEnvironment()返回的不再是默認(rèn)的 StandardEnvironment 而是替換為了 StandardServletEnvironment,在此基礎(chǔ)上查找 validateRequiredProperties()的實(shí)現(xiàn)方法,最終定位到了 AbstractEnvironment 類中:

public void validateRequiredProperties() throws MissingRequiredPropertiesException { this.propertyResolver.validateRequiredProperties();}

this.propertyResolver 指的是 PropertySourcesPropertyResolver 對(duì)象,最終具體實(shí)現(xiàn)定位在 AbstractPropertyResolver 類中:

public void validateRequiredProperties() { MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException(); Iterator var2 = this.requiredProperties.iterator();​ while(var2.hasNext()) { String key = (String)var2.next(); if (this.getProperty(key) == null) { ex.addMissingRequiredProperty(key); } }​ if (!ex.getMissingRequiredProperties().isEmpty()) { throw ex; }}

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

3.2 obtainFreshBeanFactory

該方法的實(shí)現(xiàn)如下,通過(guò) refreshBeanFactory 重置 AbstractApplicationContext 持有的 BeanFactory,然后通過(guò) getBeanFactory 獲取該對(duì)象并返回。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { this.refreshBeanFactory(); return this.getBeanFactory();}

AbstractApplicationContext 中 refreshBeanFacoty 方法和 getBeanFactory 方法都是抽象方法, 具體實(shí)現(xiàn)在 AbstractRefreshableApplicationContext 中。

protected final void refreshBeanFactory() throws BeansException { if (this.hasBeanFactory()) { //銷毀已經(jīng)存在的單例bean this.destroyBeans(); //銷毀已有的BeanFactory this.closeBeanFactory(); }​ try { //創(chuàng)建一個(gè)新的beanFactory,類型為DefaultListableBeanFactory DefaultListableBeanFactory beanFactory = this.createBeanFactory(); //設(shè)置序列化id,為實(shí)例對(duì)象內(nèi)存中的十六進(jìn)制標(biāo)識(shí) beanFactory.setSerializationId(this.getId()); //定制beanFactory,設(shè)置相關(guān)屬性,包括是否允許覆蓋同名稱的不同定義的對(duì)象以及循環(huán)依賴以及設(shè)置 this.customizeBeanFactory(beanFactory); //加載BeanDefiniton this.loadBeanDefinitions(beanFactory); synchronized(this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException var5) { throw new ApplicationContextException('I/O error parsing bean definition source for ' + this.getDisplayName(), var5); }}

loadBeanDefinitions 在 AbstractRefreshableApplicationContext 中是個(gè)抽象方法,具體實(shí)現(xiàn)是在 AbstractXmlApplicationContext 中:

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { //為當(dāng)前工廠創(chuàng)建xml解析器 XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //配置當(dāng)前環(huán)境 beanDefinitionReader.setEnvironment(this.getEnvironment()); //配置資源解析器 beanDefinitionReader.setResourceLoader(this); //配置schemas或者dtd的資源解析器,EntityResolver維護(hù)了url->schemalocation的路徑 beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); //子類提供自定義的reader的初始化方法 this.initBeanDefinitionReader(beanDefinitionReader); //加載bean定義 this.loadBeanDefinitions(beanDefinitionReader);}

在 loadBeanDefinitions 方法中傳入了 DefaultListableBeanFactory 對(duì)象,并且初始化了 XmlBeanDefinitionReader 對(duì)象,接著就是初始化 bean 工廠的一些環(huán)境、類加載器等。 繼續(xù)進(jìn)入到 loadBeanDefinitions(beanDefinitionReader)方法體中,代碼如下:

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = this.getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); }​ String[] configLocations = this.getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); }​}

這里的 configResources 和 configLocations 對(duì)應(yīng)兩種構(gòu)造函數(shù),其中 configLocations 是構(gòu)造函數(shù)A使用的。關(guān)于 loadBeanDefinitions 方法涉及的內(nèi)容比較多,我們挑一些重要的來(lái)看。以下是 AbstractBeanDefinitionReader 類中的 loadBeanDefinitions 方法。

上述方法主要做兩件事:

調(diào)用資源加載器獲取資源 resourceLoader.getResource(location) 。 真正執(zhí)行加載功能的是子類 XmlBeanDefinitionReader的loadBeanDefinitions方法 。

其中 getResources 方法是在 PathMatchingResourcePatternResolver 類實(shí)現(xiàn)的。

public Resource[] getResources(String locationPattern) throws IOException { Assert.notNull(locationPattern, 'Location pattern must not be null'); if (locationPattern.startsWith('classpath*:')) { return this.getPathMatcher().isPattern(locationPattern.substring('classpath*:'.length())) ? this.findPathMatchingResources(locationPattern) : this.findAllClassPathResources(locationPattern.substring('classpath*:'.length())); } else { int prefixEnd = locationPattern.startsWith('war:') ? locationPattern.indexOf('*/') + 1 : locationPattern.indexOf(58) + 1; return this.getPathMatcher().isPattern(locationPattern.substring(prefixEnd)) ? this.findPathMatchingResources(locationPattern) : new Resource[]{this.getResourceLoader().getResource(locationPattern)}; }}

count = this.loadBeanDefinitions(resources);中的 loadBeanDefinitions 方法具體實(shí)現(xiàn)在 XmlBeanDefinitionReader 類中。

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, 'EncodedResource must not be null'); if (this.logger.isTraceEnabled()) { this.logger.trace('Loading XML bean definitions from ' + encodedResource); }​ Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); }​ if (!((Set)currentResources).add(encodedResource)) { throw new BeanDefinitionStoreException('Detected cyclic loading of ' + encodedResource + ' - check your import definitions!'); } else { int var5; try { //將資源文件轉(zhuǎn)換為類型為InputStream的I/O流 InputStream inputStream = encodedResource.getResource().getInputStream();​ try { //從InputStream中得到xML的解析源 InputSource inputSource = new InputSource(inputStream); //編碼如果不為null, 則設(shè)置inputSource的編碼 if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); }​ var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource()); } finally { inputStream.close(); } } catch (IOException var15) { throw new BeanDefinitionStoreException('IOException parsing XML document from ' + encodedResource.getResource(), var15); } finally { ((Set)currentResources).remove(encodedResource); if (((Set)currentResources).isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); }​ }​ return var5; }}

getInputStream 方法用來(lái)加載 XML 文件,具體實(shí)現(xiàn)在 ClassPathResource 類中,

public InputStream getInputStream() throws IOException { InputStream is; if (this.clazz != null) { is = this.clazz.getResourceAsStream(this.path); } else if (this.classLoader != null) { is = this.classLoader.getResourceAsStream(this.path); } else { is = ClassLoader.getSystemResourceAsStream(this.path); }​ if (is == null) { throw new FileNotFoundException(this.getDescription() + ' cannot be opened because it does not exist'); } else { return is; }}

doLoadBeanDefinitions 用來(lái)注冊(cè) bean。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { //轉(zhuǎn)化為Document 對(duì)象 Document doc = this.doLoadDocument(inputSource, resource); //啟動(dòng)對(duì)Bean定義解析的詳細(xì)過(guò)程,會(huì)用到Spring Bean的配置規(guī)則 int count = this.registerBeanDefinitions(doc, resource); if (this.logger.isDebugEnabled()) { this.logger.debug('Loaded ' + count + ' bean definitions from ' + resource); }​ return count; } catch (BeanDefinitionStoreException var5) { throw var5; .....}

后續(xù)關(guān)聯(lián)的代碼在此就不做介紹,后期我們?cè)賹W(xué)習(xí)。

因?yàn)樵?XmlBeanDefinitionReader 中已經(jīng)將之前初始化的 DefaultListableBeanFactory 注冊(cè)進(jìn)去了,所以 XmlBeanDefinitionReader 所讀取的 BeanDefinitionHolder 都會(huì)注冊(cè)到 DefinitionListableBeanFactory 中,也就是經(jīng)過(guò)這個(gè)步驟,DefaultListableBeanFactory 的變量 beanFactory 已經(jīng)包含了所有解析好的配置。

至此通過(guò)加載 XML 文件, 將xml文件解析為對(duì)應(yīng)的 BeanDefinition ,完成了 Bean 定義的加載和注冊(cè)。

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

3.3 prepareBeanFactory

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { //設(shè)置beanFactory的classLoader為當(dāng)前context的classloader beanFactory.setBeanClassLoader(this.getClassLoader()); //設(shè)置beanFactory的表達(dá)式語(yǔ)言處理器,Spring3增加了表達(dá)式語(yǔ)言的支持, //默認(rèn)可以使用#{bean.xxx}的形式來(lái)調(diào)用相關(guān)屬性值 beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); //設(shè)置PropertyEditorRegistrar,通過(guò)PropertyEditor將xml解析出來(lái)的bean屬性(字符串)和相應(yīng)的java類型做轉(zhuǎn)換 beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment())); /** 添加后置處理器ApplicationContextAwareProcessor,在Bean初始化后自動(dòng)執(zhí)行各Aware接口的set方法,包 括ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、 ApplicationContextAware、EnvironmentAware **/ beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); beanFactory.ignoreDependencyInterface(EnvironmentAware.class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //預(yù)先設(shè)置用于自動(dòng)依賴注入的接口對(duì)象 //包括BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); //在 bean 實(shí)例化后,添加ApplicationListenerDetector,可以理解成:注冊(cè)事件監(jiān)聽(tīng)器 beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //如果存在loadTimeWeaver這個(gè)Bean,則增加對(duì)應(yīng)的后置處理器 if (beanFactory.containsBean('loadTimeWeaver')) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //添加默認(rèn)的系統(tǒng)環(huán)境bean if (!beanFactory.containsLocalBean('environment')) { beanFactory.registerSingleton('environment', this.getEnvironment()); } if (!beanFactory.containsLocalBean('systemProperties')) { beanFactory.registerSingleton('systemProperties', this.getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean('systemEnvironment')) { beanFactory.registerSingleton('systemEnvironment', this.getEnvironment().getSystemEnvironment()); }}

其中反復(fù)出現(xiàn)了 addBeanPostProcessor 方法,該方法具體實(shí)現(xiàn)在 AbstractBeanFactory 類中。

public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) { Assert.notNull(beanPostProcessor, 'BeanPostProcessor must not be null'); this.beanPostProcessors.remove(beanPostProcessor); if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) { this.hasInstantiationAwareBeanPostProcessors = true; } if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) { this.hasDestructionAwareBeanPostProcessors = true; } this.beanPostProcessors.add(beanPostProcessor);}

詳細(xì)分析下代碼發(fā)現(xiàn)上面函數(shù)主要是在以下方法進(jìn)行了擴(kuò)展:

對(duì)SPEL語(yǔ)言的支持 增加對(duì)屬性編輯器的支持 增加對(duì)一些內(nèi)置類的支持,如EnvironmentAware、MessageSourceAware的注入 設(shè)置了依賴功能可忽略的接口 注冊(cè)一些固定依賴的屬性 如果存在loadTimeWeaver這個(gè)Bean,則增加對(duì)應(yīng)的后置處理器 將相關(guān)環(huán)境變量及屬性以單例模式注冊(cè)

3.4 postProcessBeanFactory

所有 Bean 的定義已經(jīng)加載完成,但是沒(méi)有實(shí)例化,這一步可以修改 bean 定義或者增加自定義的 bean。該方法主要是承接上文中的 prepareBeanFactory 方法,增加一些后置處理器。具體實(shí)現(xiàn)在 AbstractRefreshableWebApplicationContext 類中。

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { //增加ServletContextAwareProcessor后置處理器 //用于處理ServletContextAware接口和ServletConfigAware接口中相關(guān)對(duì)象的自動(dòng)注入 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); beanFactory.ignoreDependencyInterface(ServletContextAware.class); beanFactory.ignoreDependencyInterface(ServletConfigAware.class); //注冊(cè)web環(huán)境,包括request、session、golableSession、application WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); //注冊(cè)servletContext、contextParamters、contextAttributes、servletConfig單例bean WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);}

3.5 invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) { PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors()); if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean('loadTimeWeaver')) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }}

在執(zhí)行 invokeBeanFactoryPostProcessors 方法前查看 beanFactory,對(duì)比執(zhí)行后發(fā)現(xiàn)此處有所不同。

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

在 Spring 容器中找出實(shí)現(xiàn)了 BeanFactoryPostProcessor 接口的 Bean 并執(zhí)行。Spring 容器會(huì)委托給 PostProcessorRegistrationDelegate 的 invokeBeanFactoryPostProcessors 方法執(zhí)行。

通過(guò)調(diào)試發(fā)現(xiàn),ClassPathXmlApplicationContext 類中的 beanFactoryPostProcessors 屬性為空,所以執(zhí)行 invokeBeanFactoryPostProcessors 方法時(shí)也是如此。

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

那么我們執(zhí)行該方法有什么用呢?那么還有什么地方可能存在實(shí)現(xiàn)了 BeanFactoryPostProcessor 接口的 Bean,帶著疑問(wèn),我們?nèi)ゲ榭?PostProcessorRegistrationDelegate 中的 invokeBeanFactoryPostProcessors 方法。

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { Set<String> processedBeans = new HashSet(); ArrayList regularPostProcessors; ArrayList registryProcessors; int var9; ....}

這一段代碼特別長(zhǎng),一開(kāi)始看起來(lái)肯定覺(jué)得很難,不知道從哪入手,這里我介紹一下我的學(xué)習(xí)方法,對(duì)測(cè)試代碼進(jìn)行 debug 調(diào)試,進(jìn)入該方法后一步一步往下執(zhí)行,遇到外部引用的方法記下來(lái),待會(huì)調(diào)試完畢找到該方法,然后再打斷點(diǎn)進(jìn)行調(diào)試。反復(fù)來(lái)幾遍,大概就能理解這個(gè)方法做了什么事情。

首先該方法的參數(shù) beanFactory 實(shí)際類型為 DefaultListableBeanFactory,beanFactoryPostProcessors 參數(shù)內(nèi)容為空。調(diào)試過(guò)程中發(fā)現(xiàn)比較重要的方法是 getBeanNamesForType 方法,該方法有三個(gè)參數(shù)值,具體實(shí)現(xiàn)在 DefaultListableBeanFactory 類中。

public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) { if (this.isConfigurationFrozen() && type != null && allowEagerInit) { Map<Class<?>, String[]> cache = includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType; String[] resolvedBeanNames = (String[])cache.get(type); if (resolvedBeanNames != null) { return resolvedBeanNames; } else { resolvedBeanNames = this.doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true); if (ClassUtils.isCacheSafe(type, this.getBeanClassLoader())) {cache.put(type, resolvedBeanNames); } return resolvedBeanNames; } } else { return this.doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit); }}

invokeBeanFactoryPostProcessors 方法代碼在調(diào)用 getBeanNamesForType 方法時(shí)根據(jù)第一個(gè)參數(shù)類型的不同分為兩類: BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 。其中 BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor。執(zhí)行的時(shí)候,先找出所有的 BeanDefinitionRegistryPostProcessor 執(zhí)行再找出所有 BeanFactoryPostProcessor 執(zhí)行。因?yàn)?BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,所以執(zhí)行后者時(shí)會(huì)過(guò)濾掉前者的內(nèi)容。

在調(diào)試中發(fā)現(xiàn)只有當(dāng)參數(shù)為 BeanFactoryPostProcessor.class 時(shí),才會(huì)獲取到有效的內(nèi)容。 getBeanNamesForType 方法中的關(guān)鍵部分是 doGetBeanNamesForType 方法,該方法主要是將 XML 文件中定義的實(shí)現(xiàn)了BeanFactoryPostProcessor的 bean 的 id 取出來(lái),以及將 XML 文件中定義的 bean 加載到 beanFactory 中。

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

等待 getBeanNamesForType 返回這些內(nèi)容后,接著就會(huì)實(shí)例化并初始化實(shí)現(xiàn) BeanFactoryPostProcessor 接口的類并執(zhí)行。這里比較關(guān)鍵的代碼是 invokeBeanFactoryPostProcessors 和 PropertyResourceConfigurer 類中的 postProcessBeanFactory 方法。

private static void invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) { Iterator var2 = postProcessors.iterator(); while(var2.hasNext()) { BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor)var2.next(); postProcessor.postProcessBeanFactory(beanFactory); }}public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { try { Properties mergedProps = this.mergeProperties(); this.convertProperties(mergedProps); this.processProperties(beanFactory, mergedProps); } catch (IOException var3) { throw new BeanInitializationException('Could not load properties', var3); }}

當(dāng) PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法執(zhí)行完畢后,查看 beanFactory 的狀態(tài)。

Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解

3.6 registerBeanPostProcessors

從 Spring 容器中找出的 BeanPostProcessor 接口的 Bean,并添加到 BeanFactory 內(nèi)部維護(hù)的 List 屬性中,以便后續(xù) Bean 被實(shí)例化的時(shí)候調(diào)用這個(gè) BeanPostProcessor進(jìn)行回調(diào)處理。該方法委托給了 PostProcessorRegistrationDelegate 類的 registerBeanPostProcessors 方法執(zhí)行。

同 invokeBeanFactoryPostProcessors 類似, 先從容器中獲取所有類型為 BeanPostProcessor.class 的 Bean 的 name 數(shù)組,然后通過(guò) BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class); 獲取Bean的實(shí)例,最后通過(guò) registerBeanPostProcessors(beanFactory, orderedPostProcessors);將獲取到的 BeanPostProcessor 實(shí)例添加到容器的屬性中。在實(shí)際過(guò)程中會(huì)根據(jù) AbstractBeanFactory 類中的 isTypeMatch 方法對(duì) bean 實(shí)例進(jìn)行篩選,具體順序?yàn)椋?/p> 將實(shí)現(xiàn) PriorityOrdered 接口的 BeanPostProcessor 列表添加到 beanFactory 中 將實(shí)現(xiàn) Ordered 接口的 BeanPostProcessor 列表添加到 beanFactory 中 將剩余的 BeanPostProcessor 列表添加到 beanFactory 中 將實(shí)現(xiàn) MergedBeanDefinitionPostProcessor 接口的 BeanPostProcessor 列表添加到 beanFactory 中

另外在 PostProcessorRegistrationDelegate 類中有個(gè)內(nèi)部類 BeanPostProcessorChecker,它實(shí)現(xiàn)了 BeanPostProcessor 接口,所以最后會(huì)有一個(gè) BeanPostProcessorChecker 類添加到 beanFactory 中。

最終該方法用來(lái)實(shí)例化并初始化實(shí)現(xiàn) BeanPostProcessor 接口的類,但不執(zhí)行。

3.7 initMessageSource

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

3.8 initApplicationEventMulticaster

初始化 ApplicationEventMulticaste (事件廣播器)是在方法 initApplicationEventMulticaster()中實(shí)現(xiàn)的,進(jìn)入到方法體,如下:

protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = this.getBeanFactory(); // 1、默認(rèn)使用內(nèi)置的事件廣播器,如果有的話. // 我們可以在配置文件中配置Spring事件廣播器或者自定義事件廣播器 // 例如: <bean class='org.springframework.context.event.SimpleApplicationEventMulticaster'></bean> if (beanFactory.containsLocalBean('applicationEventMulticaster')) { this.applicationEventMulticaster = (ApplicationEventMulticaster)beanFactory.getBean('applicationEventMulticaster', ApplicationEventMulticaster.class); if (this.logger.isTraceEnabled()) { this.logger.trace('Using ApplicationEventMulticaster [' + this.applicationEventMulticaster + ']'); } } else { // 2、否則,新建一個(gè)事件廣播器,SimpleApplicationEventMulticaster是spring的默認(rèn)事件廣播器 this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton('applicationEventMulticaster', this.applicationEventMulticaster); if (this.logger.isTraceEnabled()) { this.logger.trace('No ’applicationEventMulticaster’ bean, using [' + this.applicationEventMulticaster.getClass().getSimpleName() + ']'); } }}

通過(guò)源碼可以看出該方法實(shí)現(xiàn)邏輯與 initMessageSource 基本相同,其步驟如下:查找是否有 name 為 applicationEventMulticaster 的 bean,如果有則放到容器里,如果沒(méi)有,初始化一個(gè)系統(tǒng)默認(rèn)的 SimpleApplicationEventMulticaster 對(duì)象放入容器。

3.9 onRefresh

模塊方法,可用于 refresh 動(dòng)作的擴(kuò)展,默認(rèn)為空實(shí)現(xiàn)。在 SpringBoot 中主要用于啟動(dòng)內(nèi)嵌的 Web 服務(wù)器。

3.10 registerListeners

注冊(cè)監(jiān)聽(tīng)器,找出系統(tǒng)中的 ApplicationListener 對(duì)象,注冊(cè)到時(shí)間廣播器中。如果有需要提前進(jìn)行廣播的事件,則執(zhí)行廣播。

protected void registerListeners() { // 首先,注冊(cè)指定的靜態(tài)事件監(jiān)聽(tīng)器,在spring boot中有應(yīng)用 Iterator var1 = this.getApplicationListeners().iterator(); while(var1.hasNext()) { ApplicationListener<?> listener = (ApplicationListener)var1.next(); this.getApplicationEventMulticaster().addApplicationListener(listener); } // 其次,注冊(cè)普通的事件監(jiān)聽(tīng)器 String[] listenerBeanNames = this.getBeanNamesForType(ApplicationListener.class, true, false); String[] var7 = listenerBeanNames; int var3 = listenerBeanNames.length; for(int var4 = 0; var4 < var3; ++var4) { String listenerBeanName = var7[var4]; this.getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // 如果有早期事件的話,在這里進(jìn)行事件廣播 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { Iterator var9 = earlyEventsToProcess.iterator(); while(var9.hasNext()) { ApplicationEvent earlyEvent = (ApplicationEvent)var9.next(); this.getApplicationEventMulticaster().multicastEvent(earlyEvent); } }}

3.11 finishBeanFactoryInitialization

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // 判斷有無(wú)ConversionService(bean屬性類型轉(zhuǎn)換服務(wù)接口),并初始化 if (beanFactory.containsBean('conversionService') && beanFactory.isTypeMatch('conversionService', ConversionService.class)) { beanFactory.setConversionService((ConversionService)beanFactory.getBean('conversionService', ConversionService.class)); } // 如果beanFactory中不包含EmbeddedValueResolver,則向其中添加一個(gè)EmbeddedValueResolver if (!beanFactory.hasEmbeddedValueResolver()) {// EmbeddedValueResolver-->解析bean中的占位符和表達(dá)式 beanFactory.addEmbeddedValueResolver((strVal) -> { return this.getEnvironment().resolvePlaceholders(strVal); }); } // 初始化LoadTimeWeaverAware類型的bean // LoadTimeWeaverAware-->加載Spring Bean時(shí)織入第三方模塊,如AspectJ String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); String[] var3 = weaverAwareNames; int var4 = weaverAwareNames.length; for(int var5 = 0; var5 < var4; ++var5) { String weaverAwareName = var3[var5]; this.getBean(weaverAwareName); } // 釋放臨時(shí)類加載器 beanFactory.setTempClassLoader((ClassLoader)null); // 凍結(jié)緩存的BeanDefinition元數(shù)據(jù) beanFactory.freezeConfiguration(); // 初始化其他的非延遲加載的單例bean beanFactory.preInstantiateSingletons();}

實(shí)例化 BeanFactory 中已經(jīng)被注冊(cè)但是未實(shí)例化的所有實(shí)例(懶加載的不需要實(shí)例化),主要操作是 BeanFactory 的 preInstantiateSingletons 方法。該方法分為兩部分:

遍歷已經(jīng)解析出來(lái)的所有 beanDefinitionNames,如果該 BeanDefinition 不是抽象類、是單例且沒(méi)有設(shè)置懶加載,則進(jìn)行實(shí)例化和初始化。 遍歷解析出來(lái)的 beanDefinitionNames,如果獲得的單例是 SmartInitializingSingleton 的實(shí)現(xiàn)類,則會(huì)執(zhí)行 afterSingletonsInstantiated 方法。注意該方法調(diào)用只會(huì)發(fā)生在啟動(dòng)階段,后續(xù)懶加載對(duì)象再初始化的時(shí)候,不會(huì)再進(jìn)行回調(diào)。

3.12 finishRefresh

完成刷新過(guò)程,通知生命周期處理器 lifecycleProcessor 刷新過(guò)程,同時(shí)發(fā)出 ContextRefreshEvent 通知。

總結(jié)

到此這篇關(guān)于Spring IoC學(xué)習(xí)之ApplicationContext中refresh過(guò)程詳解的文章就介紹到這了,更多相關(guān)Spring ApplicationContext中refresh過(guò)程內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 97国产在线视频公开免费 | 手机日韩理论片在线播放 | 色综合久久久久久888 | 亚洲国产精品日韩在线 | 欧美一级毛片免费看 | 国产专区在线 | 亚洲国产一区二区三区综合片 | 欧美在线一二三区 | 亚洲精品专区一区二区三区 | 久久夜色邦福利网 | 亚洲精品久久久久中文 | 伊人22综合| 久久福利青草狠狠午夜 | 久久久亚洲欧美综合 | 亚洲国产欧美国产综合一区 | 日本在线不卡免 | 国产福利最新手机在线观看 | 国产亚洲精品成人一区看片 | 99一区二区三区 | 久久青草免费免费91线频观看 | 欧美一区二区三区精品国产 | 欧美日韩人成在线观看 | 亚洲精品久久久久久久久久久网站 | 欧美极品在线视频 | 亚洲精品国产综合99久久一区 | 一级做a爰片性色毛片视频图片 | 久久亚洲国产午夜精品理论片 | 手机看片日韩国产一区二区 | 亚洲精品综合久久中文字幕 | 粉嫩高中生的第一次在线观看 | 毛片一级免费 | 亚洲第一页乱 | 久久狠狠躁免费观看2020 | 亚洲国产精品久久久久久 | 亚洲精品一区二区三区在 | 亚洲性生活视频 | 欧美三级一区 | 99久久国产免费 - 99久久国产免费 | 久久国产网站 | 99在线精品视频 | 国产一级a毛片高清 |