十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
這篇文章主要講解了“Spring Ioc中各個(gè)scope的Bean是怎么創(chuàng)建的”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring Ioc中各個(gè)scope的Bean是怎么創(chuàng)建的”吧!
公司主營業(yè)務(wù):網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、移動(dòng)網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出淮北免費(fèi)做網(wǎng)站回饋大家。
代碼:
// Create bean instance. //創(chuàng)建單例Bean 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) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. //顯式地從容器單例模式Bean緩存中清除實(shí)例對(duì)象 destroySingleton(beanName); throw ex; } }); //獲取給定Bean的實(shí)例對(duì)象 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); }
這里使用了匿名內(nèi)部類,先通過createBean(beanName, mbd, args)
方法獲取一個(gè) ObjectFactory
把 ObjectFactory 作為參數(shù)傳入 getSingleton(beanName,objectFactory)
方法
使用 getSingleton(beanName,objectFactory) 方法返回的 sharedInstance作為參數(shù)傳入 getObjectForBeanInstance(sharedInstance, name, beanName, mbd)
來回去最終的Bean實(shí)例(詳情見Spring Ioc 之 Bean的加載(一))
createBean(beanName, mbd, args)
方法比較復(fù)雜,在之后的文章中會(huì)詳細(xì)分析,這里就先略過,直接看 getSingleton(beanName,objectFactory)
方法。
// DefaultSingletonBeanRegistry.java public Object getSingleton(String beanName, ObjectFactory> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); //全局加鎖 synchronized (this.singletonObjects) { // 從緩存中獲取單例bean // 因?yàn)?nbsp;singleton 模式其實(shí)就是復(fù)用已經(jīng)創(chuàng)建的 bean 所以這步驟必須檢查 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { //是否正在銷毀該bean if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } // 加載前置處理 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 初始化 bean // 這個(gè)過程其實(shí)是調(diào)用 createBean() 方法 singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } //后置處理 afterSingletonCreation(beanName); } if (newSingleton) { //加入緩存中 addSingleton(beanName, singletonObject); } } return singletonObject; } }
在這段代碼中,其實(shí)主要是做了一些準(zhǔn)備和預(yù)處理步驟,真正創(chuàng)建Bean是在singletonFactory.getObject()
方法實(shí)現(xiàn)的,而 singletonFactory是由createBean()方法創(chuàng)建后回調(diào)的參數(shù)。
那么這段代碼主要做的事情是什么呢?
嘗試從緩存中獲取單例Bean
如果已經(jīng)加載了則直接返回,否則開始加載過程
加載前置處理
獲取Bean實(shí)例
后置處理
加入緩存
beforeSingletonCreation(beanName)
是個(gè)標(biāo)記方法,我們來看代碼:
// 用于添加標(biāo)志,當(dāng)前 bean 正處于創(chuàng)建中 protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) { //添加失敗,拋出異常 throw new BeanCurrentlyInCreationException(beanName); } }
把 beanName 添加到 singletonsCurrentlyInCreation
map中,用來表示該單例bean正在創(chuàng)建,如果添加失敗,拋出異常。
通過createBean(beanName)
方法返回的 singletonFactory獲取Bean。
afterSingletonCreation(beanName)
同樣是個(gè)表示方法:
// 用于移除標(biāo)記,當(dāng)前 Bean 不處于創(chuàng)建中 protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { //移除失敗,拋出異常 throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } }
創(chuàng)建Bean之后移除創(chuàng)建標(biāo)示。
前置處理和后置處理的這個(gè)創(chuàng)建標(biāo)示,會(huì)在調(diào)用isSingletonCurrentlyInCreation(String beanName)
時(shí)用到,該方法用來判斷當(dāng)前bean是否已經(jīng)在創(chuàng)建中。
直接看代碼:
protected void addSingleton(String beanName, Object singletonObject) { synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } }
一個(gè) put、一個(gè) add、兩個(gè) remove 操作。
【put】singletonObjects 屬性,單例 bean 的緩存。
【remove】singletonFactories 屬性,單例 bean Factory 的緩存。
【remove】earlySingletonObjects 屬性,“早期”創(chuàng)建的單例 bean 的緩存。
【add】registeredSingletons 屬性,已經(jīng)注冊(cè)的單例緩存。
代碼:
//創(chuàng)建多例Bean else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. //原型模式(Prototype)是每次都會(huì)創(chuàng)建一個(gè)新的對(duì)象 Object prototypeInstance = null; try { //加載前置處理,默認(rèn)的功能是注冊(cè)當(dāng)前創(chuàng)建的原型對(duì)象 beforePrototypeCreation(beanName); //創(chuàng)建指定Bean對(duì)象實(shí)例 prototypeInstance = createBean(beanName, mbd, args); } finally { //加載后置處理,默認(rèn)的功能告訴IOC容器指定Bean的原型對(duì)象不再創(chuàng)建 afterPrototypeCreation(beanName); } //獲取給定Bean的實(shí)例對(duì)象 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); }
原型模式很簡單,直接創(chuàng)建一個(gè)新的實(shí)例就好了,不再從緩存中去獲取。beforePrototypeCreation(beanName)
前置處理,將當(dāng)前bean標(biāo)記為正在創(chuàng)建的原型。afterPrototypeCreation(beanName)
后置處理,取消當(dāng)前bean的正在創(chuàng)建標(biāo)示。
調(diào)用getObjectFrBeanInstance()
方法獲取最終bean。(詳情見Spring Ioc 之 Bean的加載(一))
//要?jiǎng)?chuàng)建的Bean既不是Singleton也不是Prototype //如:request、session、application等生命周期 else { String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); //Bean定義資源中沒有配置生命周期范圍,則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) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } }
分為以下幾個(gè)步驟:
從Scope注解中獲取scope名稱
前置處理
createBean()
后置處理
scope.get()獲取bean
getObjectForBeanInstance()方法獲取Bean
核心流程與原型模式一樣,只不過這里調(diào)用了scope.get()來獲取bean。
Object get(String name, ObjectFactory> objectFactory);
scope.get()是一個(gè)接口,它有多種實(shí)現(xiàn)類:
我們看一下spring自帶的一個(gè)實(shí)現(xiàn) SimpleThreadScope:
//SimpleThreadScope.java private final ThreadLocal
其他scope的實(shí)現(xiàn)就不一一去看了,感興趣的朋友可以自己看一下。
總結(jié)
上面的代碼中有2個(gè)重要方法:
createBean(beanName, mbd, args)
getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd)
這2個(gè)方法在3個(gè)代碼分支中都用到了,createBean
下篇文章會(huì)詳細(xì)分析,getObjectForBeanInstance
方法在Spring Ioc 之 Bean的加載(一)中已經(jīng)分析過了。
這里再引用下《Spring 源碼深度解析》對(duì)該方法的分析:
這個(gè)方法主要是驗(yàn)證以下我們得到的 bean 的正確性,其實(shí)就是檢測(cè)當(dāng)前 bean 是否是 FactoryBean 類型的 bean 。
如果是,那么需要調(diào)用該 bean 對(duì)應(yīng)的 FactoryBean 實(shí)例的 getObject() 方法,作為返回值。
無論是從緩存中獲得到的 bean 還是通過不同的 scope 策略加載的 bean 都只是最原始的 bean 狀態(tài),并不一定就是我們最終想要的 bean。
舉個(gè)例子,假如我們需要對(duì)工廠 bean 進(jìn)行處理,那么這里得到的其實(shí)是工廠 bean 的初始狀態(tài),但是我們真正需要的是工廠 bean 中定義 factory-method 方法中返回的 bean,而 getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) 方法,就是完成這個(gè)工作的。
感謝各位的閱讀,以上就是“Spring Ioc中各個(gè)scope的Bean是怎么創(chuàng)建的”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對(duì)Spring Ioc中各個(gè)scope的Bean是怎么創(chuàng)建的這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!