日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

5.0:Spring-bean的加载

發布時間:2024/9/5 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 5.0:Spring-bean的加载 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內容來自<Spring深度解析>,之后的不一一復述!

在Spring中,最基本的IOC容器接口是BeanFactory - 這個接口為具體的IOC容器的實現作了最基本的功能規定 - 不管怎么著,作為IOC容器,這些接口你必須要滿足應用程序的最基本要求:?

bean加載的探索。bean加載的功能實現遠比bean的解析要復雜得多, 對于加載bean的功能,在Spring中的調用方式為:

?

MyBean?bean=(MyBean)?bf.getBean("myBean")

?

這句代碼實現了什么樣的功能呢?我們可以先快速體驗一下Spring中代碼是如何實現的。

?

1 public Object getBean(String name) throws BeansException { 2 return doGetBean(name, null, null, false); 3 }

?

1 @SuppressWarnings("unchecked") 2 protected <T> T doGetBean(final String name, final Class<T> requiredType, 3 final Object[] args, boolean typeCheckOnly) throws BeansException { 4 // 提取對應的beanName 5 final String beanName = transformedBeanName(name); 6 Object bean; 7 8 // Eagerly check singleton cache for manually registered singletons. 9 /* 10 * 檢查緩存中或者實例工廠中是否有對應的實例 為什么首先會使用這段代碼呢, 因為在創建單例bean的時候會存在依賴注入的情況,而在創建依賴的時候為了避免循環依賴, 11 * Spring創建bean的原則是不等bean創建完成就會將創建bean的ObjectFactory提早曝光 12 * 也就是將ObjectFactory加入到緩存中,一旦下個bean創建時候需要依賴上個bean則直接使用Object        Factory 13 */ 14 // 直接嘗試從緩存獲取或者singletonFactories中的ObjectFactory中獲取 15 Object sharedInstance = getSingleton(beanName); 16 if (sharedInstance != null && args == null) { 17 if (logger.isDebugEnabled()) { 18 if (isSingletonCurrentlyInCreation(beanName)) { 19 logger.debug("Returning eagerly cached instance of singleton bean '" 20 + beanName 21 + "' that is not fully initialized yet - a consequence of a circular reference"); 22 } 23 else { 24 logger.debug("Returning cached instance of singleton bean '" 25 + beanName + "'"); 26 } 27 } 28 // 返回對應的實例,有時候存在諸如BeanFactory的情況并不是直接返回實例本身而是返回指定方法返回的實例 29 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); 30 } 31 32 else { 33 // Fail if we're already creating this bean instance: 34 // We're assumably within a circular reference. 35 // 只有在單例情況才會嘗試解決循環依賴,原型模式情況下,如果存在 36 // A中有B的屬性,B中有A的屬性,那么當依賴注入的時候,就會產生當A還未創建完的時候因為 37 // 對于B的創建再次返回創建A,造成循環依賴,也就是下面的情況 38 if (isPrototypeCurrentlyInCreation(beanName)) { 39 throw new BeanCurrentlyInCreationException(beanName); 40 } 41 42 // Check if bean definition exists in this factory. 43 // 如果beanDefinitionMap中也就是在所有已經加載的類中不包括beanName則嘗試從parentBeanFactory中檢測 44 BeanFactory parentBeanFactory = getParentBeanFactory(); 45 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { 46 // Not found -> check parent. 47 String nameToLookup = originalBeanName(name); 48 // 遞歸到BeanFactory中尋找 49 if (args != null) { 50 // Delegation to parent with explicit args. 51 return (T) parentBeanFactory.getBean(nameToLookup, args); 52 } 53 else { 54 // No args -> delegate to standard getBean method. 55 return parentBeanFactory.getBean(nameToLookup, requiredType); 56 } 57 } 58 // 如果不是僅僅做類型檢查則是創建bean,這里要進行記錄 59 if (!typeCheckOnly) { 60 markBeanAsCreated(beanName); 61 } 62 63 try { 64 // 將存儲XML配置文件的GernericBeanDefinition轉換為RootBeanDefinition,如果指定BeanName是子Bean的話同時會合并父類的相關屬性 65 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 66 checkMergedBeanDefinition(mbd, beanName, args); 67 68 // Guarantee initialization of beans that the current bean depends on. 69 String[] dependsOn = mbd.getDependsOn(); 70 // 若存在依賴則需要遞歸實例化依賴的bean 71 if (dependsOn != null) { 72 for (String dependsOnBean : dependsOn) { 73 if (isDependent(beanName, dependsOnBean)) { 74 throw new BeanCreationException( 75 "Circular depends-on relationship between '" 76 + beanName + "' and '" + dependsOnBean + "'"); 77 } 78 // 緩存依賴調用 79 registerDependentBean(dependsOnBean, beanName); 80 getBean(dependsOnBean); 81 } 82 } 83 84 // 實例化依賴的bean后便可以實例化mbd本身了 85 // Create bean instance. 86 if (mbd.isSingleton()) {// singleton模式的創建 87 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { 88 89 @Override 90 public Object getObject() throws BeansException { 91 try { 92 return createBean(beanName, mbd, args); 93 } 94 catch (BeansException ex) { 95 // Explicitly remove instance from singleton cache: It 96 // might have been put there 97 // eagerly by the creation process, to allow for circular 98 // reference resolution. 99 // Also remove any beans that received a temporary 100 // reference to the bean. 101 destroySingleton(beanName); 102 throw ex; 103 } 104 } 105 }); 106 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 107 } 108 109 else if (mbd.isPrototype()) { // prototype模式的創建(new) 110 // It's a prototype -> create a new instance. 111 Object prototypeInstance = null; 112 try { 113 beforePrototypeCreation(beanName); 114 prototypeInstance = createBean(beanName, mbd, args); 115 } 116 finally { 117 afterPrototypeCreation(beanName); 118 } 119 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, 120 mbd); 121 } 122 123 else {// 指定的scope上實例化bean 124 String scopeName = mbd.getScope(); 125 final Scope scope = this.scopes.get(scopeName); 126 if (scope == null) { 127 throw new IllegalStateException("No Scope registered for scope '" 128 + scopeName + "'"); 129 } 130 try { 131 Object scopedInstance = scope.get(beanName, 132 new ObjectFactory<Object>() { 133 134 @Override 135 public Object getObject() throws BeansException { 136 beforePrototypeCreation(beanName); 137 try { 138 return createBean(beanName, mbd, args); 139 } 140 finally { 141 afterPrototypeCreation(beanName); 142 } 143 } 144 }); 145 bean = getObjectForBeanInstance(scopedInstance, name, beanName, 146 mbd); 147 } 148 catch (IllegalStateException ex) { 149 throw new BeanCreationException( 150 beanName, 151 "Scope '" 152 + scopeName 153 + "' is not active for the current thread; " 154 + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", 155 ex); 156 } 157 } 158 } 159 catch (BeansException ex) { 160 cleanupAfterBeanCreationFailure(beanName); 161 throw ex; 162 } 163 } 164 165 // Check if required type matches the type of the actual bean instance. 166 // 檢查需要的類型是否符合bean的實際類型 167 if (requiredType != null && bean != null 168 && !requiredType.isAssignableFrom(bean.getClass())) { 169 try { 170 return getTypeConverter().convertIfNecessary(bean, requiredType); 171 } 172 catch (TypeMismatchException ex) { 173 if (logger.isDebugEnabled()) { 174 logger.debug( 175 "Failed to convert bean '" + name + "' to required type [" 176 + ClassUtils.getQualifiedName(requiredType) + "]", ex); 177 } 178 throw new BeanNotOfRequiredTypeException(name, requiredType, 179 bean.getClass()); 180 } 181 } 182 return (T) bean; 183 }

?

?

僅從代碼量上就能看出來bean的加載經歷了一個相當復雜的過程,其中涉及各種各樣的考慮。相信讀者細心閱讀上面的代碼,并參照部分代碼注釋,是可以粗略地了解整個Spring加載bean的過程。對于加載過程中所涉及的步驟大致如下。

1)轉換對應beanName

或許很多人不理解轉換對應beanName是什么意思,傳入的參數name不就是beanName嗎?其實不是,這里傳入的參數可能是別名,也可能是FactoryBean,所以需要進行一系列的解析,這些解析內容包括如下內容。

??去除FactoryBean的修飾符,也就是如果name="&aa",那么會首先去除&而使name="aa"

??取指定alias所表示的最終beanName,例如別名A指向名稱為Bbean則返回B;若別名A指向別名B,別名B又指向名稱為Cbean則返回C

?

2)嘗試從緩存中加載單例。

?

單例在Spring的同一個容器內只會被創建一次,后續再獲取bean,就直接從單例緩存中獲取了。當然這里也只是嘗試加載,首先嘗試從緩存中加載,如果加載不成功則再次嘗試從singletonFactories中加載。因為在創建單例bean的時候會存在依賴注入的情況,而在創建依賴的時候為了避免循環依賴,在Spring中創建bean的原則是不等bean創建完成就會將創建beanObjectFactory提早曝光加入到緩存中,一旦下一個bean創建時候需要依賴上一個bean則直接使用ObjectFactory(后面章節會對循環依賴重點講解)。

?

3bean的實例化。

?

如果從緩存中得到了bean的原始狀態,則需要對bean進行實例化。這里有必要強調一下,緩存中記錄的只是最原始的bean狀態,并不一定是我們最終想要的bean。舉個例子,假如我們需要對工廠bean進行處理,那么這里得到的其實是工廠bean的初始狀態,但是我們真正需要的是工廠bean中定義的factory-method方法中返回的bean,而getObjectForBeanInstance就是完成這個工作的,后續會詳細講解。

?

4)原型模式的依賴檢查。

?

只有在單例情況下才會嘗試解決循環依賴,如果存在A中有B的屬性,B中有A的屬性,那么當依賴注入的時候,就會產生當A還未創建完的時候因為對于B的創建再次返回創建A,造成循環依賴,也就是情況:isPrototypeCurrentlyInCreation(beanName)判斷true

?

5)檢測parentBeanFactory

?

從代碼上看,如果緩存沒有數據的話直接轉到父類工廠上去加載了,這是為什么呢?

?

可能讀者忽略了一個很重要的判斷條件:parentBeanFactory?!=?null?&&?!containsBean?Definition?(beanName)parentBeanFactory?!=?nullparentBeanFactory如果為空,則其他一切都是浮云,這個沒什么說的,但是!containsBeanDefinition(beanName)就比較重要了,它是在檢測如果當前加載的XML配置文件中不包含beanName所對應的配置,就只能到parentBeanFactory去嘗試下了,然后再去遞歸的調用getBean方法。

?

6)將存儲XML配置文件的GernericBeanDefinition轉換為RootBeanDefinition

?

因為從XML配置文件中讀取到的Bean信息是存儲在GernericBeanDefinition中的,但是所有的Bean后續處理都是針對于RootBeanDefinition的,所以這里需要進行一個轉換,轉換的同時如果父類bean不為空的話,則會一并合并父類的屬性。

?

7)尋找依賴。

?

因為bean的初始化過程中很可能會用到某些屬性,而某些屬性很可能是動態配置的,并且配置成依賴于其他的bean,那么這個時候就有必要先加載依賴的bean,所以,在Spring的加載順尋中,在初始化某一個bean的時候首先會初始化這個bean所對應的依賴。

?

8)針對不同的scope進行bean的創建。

?

我們都知道,在Spring中存在著不同的scope,其中默認的是singleton,但是還有些其他的配置諸如prototyperequest之類的。在這個步驟中,Spring會根據不同的配置進行不同的初始化策略。

?

9)類型轉換。

?

程序到這里返回bean后已經基本結束了,通常對該方法的調用參數requiredType是為空的,但是可能會存在這樣的情況,返回的bean其實是個String,但是requiredType卻傳入Integer類型,那么這時候本步驟就會起作用了,它的功能是將返回的bean轉換為requiredType所指定的類型。當然,String轉換為Integer是最簡單的一種轉換,在Spring中提供了各種各樣的轉換器,用戶也可以自己擴展轉換器來滿足需求。

?

?

經過上面的步驟后bean的加載就結束了,這個時候就可以返回我們所需要的bean了,圖5-1直觀地反映了整個過程。其中最重要的就是步驟(8),針對不同的scope進行bean的創建,你會看到各種常用的Spring特性在這里的實現。

?

在細化分析各個步驟提供的功能前,我們有必要先了解下FactoryBean的用法。

?

?

?

?

?

?

圖5-1??bean的獲取過程

?

?

?

?

?

?

?

?

?

?

轉載于:https://www.cnblogs.com/mjorcen/p/3582956.html

總結

以上是生活随笔為你收集整理的5.0:Spring-bean的加载的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美日韩中文字幕在线视频 | 色八区| 九九热最新网址 | 成年人在线免费观看 | 国产做爰免费视频观看 | 中文字幕在线观看网站 | 丁香花在线影院观看在线播放 | 在线免费观看一区二区 | 善良的女朋友在线观看 | 我要看黄色大片 | 人体内射精一区二区三区 | 国产伦精品一区二区三区千人斩 | 一级片免费在线 | 日韩在线视频免费观看 | 日本人体视频 | 青娱乐最新官网 | 国产成人精品一区二区三区无码熬 | 老司机午夜剧场 | 少妇人妻综合久久中文字幕 | 加勒比hezyo黑人专区 | 国产人妻久久精品一区二区三区 | 免费观看日韩 | 久久午夜夜伦鲁鲁片 | 超碰xxx| 日韩啊啊啊| 色悠久久综合 | 国产福利短视频 | 国产一区二区不卡 | 伊人成人22 | 福利色播| 午夜一区二区三区免费 | 国产第一页第二页 | 日韩精品中文字幕一区二区 | 欧美性日韩 | 黄色一级片在线免费观看 | 亚洲成人激情在线 | 午夜精品一区二区在线观看 | 久久久久久av无码免费看大片 | 高潮又黄又刺激 | 精品免费观看 | 国产粉嫩av| 亚洲视频91| 人妻少妇精品无码专区久久 | 综合伊人久久 | 中文字幕色网 | 蜜臀aⅴ国产精品久久久国产老师 | 波多野结衣亚洲天堂 | 一区二区在线视频 | 黄色一级一片免费播放 | 亚洲视频久久久 | 日韩成人自拍 | 欧美日韩卡一卡二 | 搡8o老女人老妇人老熟 | 欧美一区二区三区在线观看视频 | 97av视频 | 欧美日韩亚洲一区二区 | 99久久久无码国产 | 国产福利一区在线 | 国产成人久久精品77777综合 | 日韩激情一区二区三区 | 超碰91人人| 丰满人妻一区二区三区53 | 国产97自拍 | 麻豆高清视频 | 亚洲AV无码成人精品区东京热 | 日韩r级在线观看 | 亚洲成av人影院 | 日韩 欧美 自拍 | 婷婷久久久久久 | 亚洲三级在线看 | 色噜噜视频 | 国产日韩欧美精品一区二区 | 国产成人精品一区二区三区免费 | 捆绑束缚调教 | 18av在线播放| 久久人人爽人人爽人人片av高清 | 日本人妻不卡一区二区三区中文字幕 | 在线看片你懂 | 97久久久久久久久久 | 黄色在线免费看 | 91视频在线免费看 | 国产一区二区小视频 | 国产精品入口麻豆 | 91干视频| 国产a大片| 天天摸日日干 | 亚洲一区二区久久 | 99精品视频免费版的特色功能 | 男人的天堂99 | 黄色国产在线播放 | 无码精品人妻一区二区三区湄公河 | 午夜xxxx| 超碰成人在线观看 | 天天色天天色天天色 | 国产精品夜夜夜爽阿娇 | jizz日本大全 | 800av免费在线观看 | 91亚洲网 | 亚洲精品va |