摘要:初始化我們知道容器初始化后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的定義進(jìn)行的初始化操作,所以我們分析源碼的入口也就是在容器初始化的入口,分析容器初始化后在什么地方開(kāi)始第一次的初始化。
前言
Spring IOC容器在初始化之后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的bean定義進(jìn)行bean的初始化操作,同時(shí)會(huì)也涉及到Bean的后置處理器以及DI(依賴注入)等行為。對(duì)于Bean的初始化,Spring是通過(guò)第一次調(diào)用getBean方法向容器獲取bean實(shí)例時(shí)進(jìn)行的。下面的源碼分析也是基于getBean()作為入口一步步去了解Spring是如何初始化單例Bean的。
Bean初始化我們知道Spring IOC容器初始化后會(huì)對(duì)容器中非懶加載的,單例的以及非抽象的bean定義進(jìn)行bean的初始化操作,所以我們分析源碼的入口也就是在容器初始化的入口,分析容器初始化后Spring在什么地方開(kāi)始第一次的Bean初始化。
在之前的一篇博文Spring專題之IOC源碼分析中有分析到Spring IOC容器初始化的過(guò)程,過(guò)程源碼如下:
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //調(diào)用容器準(zhǔn)備刷新的方法,獲取容器的當(dāng)時(shí)時(shí)間,同時(shí)給容器設(shè)置同步標(biāo)識(shí) prepareRefresh(); // Tell the subclass to refresh the internal bean factory. //告訴子類啟動(dòng)refreshBeanFactory()方法,Bean定義資源文件的載入從 //子類的refreshBeanFactory()方法啟動(dòng) ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. //為BeanFactory配置容器特性,例如類加載器、事件處理器等 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. //為容器的某些子類指定特殊的BeanPost事件處理器 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. //調(diào)用所有注冊(cè)的BeanFactoryPostProcessor的Bean invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. //為BeanFactory注冊(cè)BeanPost事件處理器. //BeanPostProcessor是Bean后置處理器,用于監(jiān)聽(tīng)容器觸發(fā)的事件 registerBeanPostProcessors(beanFactory); // Initialize message source for this context. //初始化信息源,和國(guó)際化相關(guān). initMessageSource(); // Initialize event multicaster for this context. //初始化容器事件傳播器. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. //調(diào)用子類的某些特殊Bean初始化方法 onRefresh(); // Check for listener beans and register them. //為事件傳播器注冊(cè)事件監(jiān)聽(tīng)器. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. //初始化所有剩余的單例Bean finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. //初始化容器的生命周期事件處理器,并發(fā)布容器的生命周期事件 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. //銷毀已創(chuàng)建的Bean destroyBeans(); // Reset "active" flag. //取消refresh操作,重置容器的同步標(biāo)識(shí). 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(); } } }
上述源碼可以觀察看在IOC容器被初始化后進(jìn)行了很多其他的操作,但這些現(xiàn)在我們暫時(shí)不關(guān)心,我們需要關(guān)注的只有finishBeanFactoryInitialization這個(gè)方法,這個(gè)方法的作用就是初始化所有剩余的單例Bean,所以這也是我們以下分析源碼的入口。
finishBeanFactoryInitialization方法源碼如下:
//對(duì)配置了lazy-init屬性的Bean進(jìn)行預(yù)實(shí)例化處init屬性的Bean進(jìn)行預(yù)實(shí)例化處理理 protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { .... // Instantiate all remaining (non-lazy-init) singletons. //對(duì)配置了lazy-init屬性的單態(tài)模式Bean進(jìn)行預(yù)實(shí)例化處理 beanFactory.preInstantiateSingletons(); }
這個(gè)方法前面一些處理暫時(shí)不看,可以知道最后調(diào)用了ConfigurableListableBeanFactory的preInstantiateSingletons方法,也就是對(duì)配置了lazy-init屬性的單態(tài)模式Bean進(jìn)行預(yù)實(shí)例化處理。
下面進(jìn)入preInstantiateSingletons方法分析,源碼如下:
//對(duì)配置lazy-init屬性單態(tài)Bean的預(yù)實(shí)例化 public void preInstantiateSingletons() throws BeansException { if (this.logger.isDebugEnabled()) { this.logger.debug("Pre-instantiating singletons in " + this); } ListbeanNames = new ArrayList<>(this.beanDefinitionNames); for (String beanName : beanNames) { //獲取指定名稱的Bean定義 RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //Bean不是抽象的,是單態(tài)模式的,且lazy-init屬性配置為false if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //如果指定名稱的bean是創(chuàng)建容器的Bean if (isFactoryBean(beanName)) { //FACTORY_BEAN_PREFIX=”&”,當(dāng)Bean名稱前面加”&”符號(hào) //時(shí),獲取的是產(chǎn)生容器對(duì)象本身,而不是容器產(chǎn)生的Bean. //調(diào)用getBean方法,觸發(fā)容器對(duì)Bean實(shí)例化和依賴注入過(guò)程 final FactoryBean> factory = (FactoryBean>) getBean(FACTORY_BEAN_PREFIX + beanName); //標(biāo)識(shí)是否需要預(yù)實(shí)例化 boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { //一個(gè)匿名內(nèi)部類 isEagerInit = AccessController.doPrivileged((PrivilegedAction ) () -> ((SmartFactoryBean>) factory).isEagerInit(), getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean>) factory).isEagerInit()); } if (isEagerInit) { //調(diào)用getBean方法,觸發(fā)容器對(duì)Bean實(shí)例化和依賴注入過(guò)程 getBean(beanName); } } else { //調(diào)用getBean方法,觸發(fā)容器對(duì)Bean實(shí)例化和依賴注入過(guò)程 getBean(beanName); } } } //觸發(fā)bean初始化后的回調(diào) ... }
通過(guò)源碼解析,我們可以看到這里對(duì)于不是抽象的,是單態(tài)模式的,且lazy-init屬性配置為false的Bean定義進(jìn)行初始化,而初始化過(guò)程正是調(diào)用了getBean方法。下面我們進(jìn)入getBean方法觀察Spring對(duì)bean的初始化過(guò)程。getBean方法及相關(guān)調(diào)用源碼如下:
//獲取IOC容器中指定名稱的Bean public Object getBean(String name) throws BeansException { //doGetBean才是真正向IoC容器獲取被管理Bean的過(guò)程 return doGetBean(name, null, null, false); } //真正實(shí)現(xiàn)向IOC容器獲取Bean的功能,也是觸發(fā)依賴注入功能的地方 protectedT doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { //根據(jù)指定的名稱獲取被管理Bean的名稱,剝離指定名稱中對(duì)容器的相關(guān)依賴,如果指定的是別名,將別名轉(zhuǎn)換為規(guī)范的Bean名稱 final String beanName = transformedBeanName(name); Object bean; //先從緩存中取是否已經(jīng)有被創(chuàng)建過(guò)的單態(tài)類型的Bean,對(duì)于單例模式的Bean整個(gè)IOC容器中只創(chuàng)建一次,不需要重復(fù)創(chuàng)建 Object sharedInstance = getSingleton(beanName); //IOC容器創(chuàng)建單例模式Bean實(shí)例對(duì)象 if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { //如果指定名稱的Bean在容器中已有單例模式的Bean被創(chuàng)建 //直接返回已經(jīng)創(chuàng)建的Bean if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean "" + beanName + "" that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean "" + beanName + """); } } //獲取給定Bean的實(shí)例對(duì)象,主要是完成FactoryBean的相關(guān)處理。注意:BeanFactory是管理容器中Bean的工廠,而FactoryBean是創(chuàng)建創(chuàng)建對(duì)象的工廠Bean,兩者之間有區(qū)別 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //緩存沒(méi)有正在創(chuàng)建的單例模式Bean,緩存中已經(jīng)有已經(jīng)創(chuàng)建的原型模式Bean,但是由于循環(huán)引用的問(wèn)題導(dǎo)致實(shí)例化對(duì)象失敗 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //對(duì)IOC容器中是否存在指定名稱的BeanDefinition進(jìn)行檢查,首先檢查是否能在當(dāng)前的BeanFactory中獲取的所需要的Bean,如果不能則委托當(dāng)前容器的父級(jí)容器去查找,如果還是找不到則沿著容器的繼承體系向父級(jí)容器查找 BeanFactory parentBeanFactory = getParentBeanFactory(); //當(dāng)前容器的父級(jí)容器存在,且當(dāng)前容器中不存在指定名稱的Bean if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { //解析指定Bean名稱的原始名稱 String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { //委派父級(jí)容器根據(jù)指定名稱和顯式的參數(shù)查找 return (T) parentBeanFactory.getBean(nameToLookup, args); } else { //委派父級(jí)容器根據(jù)指定名稱和類型查找 return parentBeanFactory.getBean(nameToLookup, requiredType); } } //創(chuàng)建的Bean是否需要進(jìn)行類型驗(yàn)證,一般不需要 if (!typeCheckOnly) { //向容器標(biāo)記指定的Bean已經(jīng)被創(chuàng)建 markBeanAsCreated(beanName); } try { //根據(jù)指定Bean名稱獲取其父級(jí)的Bean定義 //主要解決Bean繼承時(shí)子類合并父類公共屬性問(wèn)題 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); //獲取當(dāng)前Bean所有依賴Bean的名稱 String[] dependsOn = mbd.getDependsOn(); //如果當(dāng)前Bean有依賴Bean if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between "" + beanName + "" and "" + dep + """); } //遞歸調(diào)用getBean方法,獲取當(dāng)前Bean的依賴Bean registerDependentBean(dep, beanName); //把被依賴Bean注冊(cè)給當(dāng)前依賴的Bean getBean(dep); } } //創(chuàng)建單例模式Bean的實(shí)例對(duì)象 if (mbd.isSingleton()) { //這里使用了一個(gè)匿名內(nèi)部類,創(chuàng)建Bean實(shí)例對(duì)象,并且注冊(cè)給所依賴的對(duì)象 sharedInstance = getSingleton(beanName, () -> { try { //創(chuàng)建一個(gè)指定Bean實(shí)例對(duì)象,如果有父級(jí)繼承,則合并子類和父類的定義 return createBean(beanName, mbd, args); } catch (BeansException ex) { //顯式地從容器單例模式Bean緩存中清除實(shí)例對(duì)象 destroySingleton(beanName); throw ex; } }); //獲取給定Bean的實(shí)例對(duì)象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } //IOC容器創(chuàng)建原型模式Bean實(shí)例對(duì)象 else if (mbd.isPrototype()) { //原型模式(Prototype)是每次都會(huì)創(chuàng)建一個(gè)新的對(duì)象 Object prototypeInstance = null; try { //回調(diào)beforePrototypeCreation方法,默認(rèn)的功能是注冊(cè)當(dāng)前創(chuàng)建的原型對(duì)象 beforePrototypeCreation(beanName); //創(chuàng)建指定Bean對(duì)象實(shí)例 prototypeInstance = createBean(beanName, mbd, args); } finally { //回調(diào)afterPrototypeCreation方法,默認(rèn)的功能告訴IOC容器指定Bean的原型對(duì)象不再創(chuàng)建 afterPrototypeCreation(beanName); } //獲取給定Bean的實(shí)例對(duì)象 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } //要?jiǎng)?chuàng)建的Bean既不是單例模式,也不是原型模式,則根據(jù)Bean定義資源中配置的生命周期范圍,選擇實(shí)例化Bean的合適方法,這種在Web應(yīng)用程序中,比較常用,如:request、session、application等生命周期 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); //Bean定義資源中沒(méi)有配置生命周期范圍,則Bean定義不合法 if (scope == null) { throw new IllegalStateException("No Scope registered for scope name "" + scopeName + """); } try { //這里又使用了一個(gè)匿名內(nèi)部類,獲取一個(gè)指定生命周期范圍的實(shí)例 Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); //獲取給定Bean的實(shí)例對(duì)象 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { ... } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } //對(duì)創(chuàng)建的Bean實(shí)例對(duì)象進(jìn)行類型檢查 if (requiredType != null && !requiredType.isInstance(bean)) { try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { ... } } return (T) bean; }
這里通過(guò)上述源碼的分析,總結(jié)以下Spring初始化bean的過(guò)程,首先Spring會(huì)去緩存中搜索是否已存在bean實(shí)例,如果存在則直接取出返回,不存在就判斷是否存在父容器,存在則調(diào)用父容器的getBean方法進(jìn)行初始化,否則通過(guò)判斷bean定義是否是單例bean,是否是原型bena進(jìn)行相關(guān)的初始化操作,可以知道最后都是調(diào)用了createBean方法去創(chuàng)建bean的。
至此,通過(guò)上述的源碼分析,我們對(duì)Spring在IOC初始化后對(duì)bean的初始化過(guò)程有了大致的了解,下篇博客會(huì)繼續(xù)這篇通過(guò)源碼分析Spring初始化的具體過(guò)程。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77002.html
摘要:前言這篇是專題初始化的第二篇,主要對(duì)初始化具體過(guò)程的源碼分析。上篇博客專題之初始化源碼分析中我們對(duì)如何開(kāi)始初始化以及初始化的總體過(guò)程有了大致的了解,接下來(lái)就繼續(xù)上篇博客的結(jié)尾處開(kāi)始來(lái)分析初始化的具體過(guò)程。 前言 這篇是Spring專題Bean初始化的第二篇,主要對(duì)bean初始化具體過(guò)程的源碼分析。上篇博客Spring專題之Bean初始化源碼分析(1)中我們對(duì)Spring如何開(kāi)始初始化b...
摘要:前言以下源碼基于版本解析。實(shí)現(xiàn)源碼分析對(duì)于的實(shí)現(xiàn),總結(jié)來(lái)說(shuō)就是定位加載和注冊(cè)。定位就是需要定位配置文件的位置,加載就是將配置文件加載進(jìn)內(nèi)存注冊(cè)就是通過(guò)解析配置文件注冊(cè)。下面我們從其中的一種使用的方式一步一步的分析的實(shí)現(xiàn)源碼。 前言 以下源碼基于Spring 5.0.2版本解析。 什么是IOC容器? 容器,顧名思義可以用來(lái)容納一切事物。我們平常所說(shuō)的Spring IOC容器就是一個(gè)可以容...
摘要:的在單例被破壞時(shí)由進(jìn)行方法調(diào)用。定義并實(shí)現(xiàn)這兩個(gè)接口容器創(chuàng)建完成注解是的縮寫,意思是規(guī)范提案。在創(chuàng)建完成并且屬性賦值完成來(lái)執(zhí)行初始化方法在容器銷毀之前回調(diào)通知支持自動(dòng)裝配,類似。 Spring注解應(yīng)用篇--IOC容器Bean生命周期 這是Spring注解專題系類文章,本系類文章適合Spring入門者或者原理入門者,小編會(huì)在本系類文章下進(jìn)行企業(yè)級(jí)應(yīng)用實(shí)戰(zhàn)講解以及spring源碼跟進(jìn)。本文...
摘要:入門篇學(xué)習(xí)總結(jié)時(shí)間年月日星期三說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。主要的功能是日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等等。 《Spring入門篇》學(xué)習(xí)總結(jié) 時(shí)間:2017年1月18日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:https://github.com/zccodere/s...個(gè)人學(xué)習(xí)源碼:https://git...
閱讀 1590·2023-04-26 01:36
閱讀 2748·2021-10-08 10:05
閱讀 2804·2021-08-05 09:57
閱讀 1563·2019-08-30 15:52
閱讀 1223·2019-08-30 14:12
閱讀 1343·2019-08-30 11:17
閱讀 3153·2019-08-29 13:07
閱讀 2458·2019-08-29 12:35