亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

springIOC源碼分析(3)

2019-11-14 15:24:57
字體:
來源:轉載
供稿:網友

1.IOC容器的依賴注入

        SPRing中,依賴注入是在用戶第一次向IOC容器索要Bean時觸發的(通過getBean方法)。

       在BeanFactory中我們看到getBean(String…)函數,它的具體實現在AbstractBeanFactory中:

[java] view plaincopy
 
  1. public Object getBean(String name) throws BeansException {  
  2.         return doGetBean(name, null, null, false);  
  3. }  

        可以看到具體的注入過程轉移到doGetBean(String…)中,在這個方法中,它首先從緩存中取,如果單件模式的bean已經被創建,則這種bean請求不需要重復的創建,調用

[java] view plaincopy
 
  1. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  

        跟蹤進入getObjectForBeanInstance(…,null),可以知道因為最后的RootBeanDefinition參數是null,所以執行的是:

[java] view plaincopy
 
  1. if (mbd == null) {  
  2.     object = getCachedObjectForFactoryBean(beanName);  
  3. }  

        而getCachedObjectForFactoryBean(beanName)中實現,其實現很簡單,就是在緩存的bean map中查找bean返回。

        繼續回到doGetBean(String…)方法中:

[java] view plaincopy
 
  1.          //取當前bean的所有依賴bean,這樣就會觸發getBean的遞歸調用,直至取到一個沒有任何依賴的bean為止  
  2.     String[] dependsOn = mbd.getDependsOn();  
  3.     if (dependsOn != null) {  
  4.         for (String dependsOnBean : dependsOn) {  
  5.             getBean(dependsOnBean);  
  6.                       //注冊依賴的bean實例,具體實現過程在DefaultSingletonBeanRegistry中實現,其實就是將依賴的bean添加到依賴的hashmap中  
  7.             registerDependentBean(dependsOnBean, beanName);  
  8.         }  
  9.     }  
  10.     //通過調用createBean來,創建單例bean的實例  
  11.     if (mbd.isSingleton()) {  
  12.         sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  13.            public Object getObject() throws BeansException {  
  14.              try {  
  15.               return createBean(beanName, mbd, args);  
  16.              }  
  17.              catch (BeansException ex) {  
  18.             destroySingleton(beanName);  
  19.             throw ex;  
  20.              }  
  21.                 }  
  22.             });  
  23.             bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  24.     }  
  25.     //同樣調用createBean創建prototype的bean實例  
  26.     else if (mbd.isPrototype()) {  
  27.         // It's a prototype -> create a new instance.  
  28.         Object prototypeInstance = null;  
  29.         try {  
  30.             beforePrototypeCreation(beanName);  
  31.             prototypeInstance = createBean(beanName, mbd, args);  
  32.         }  
  33.         finally {  
  34.             afterPrototypeCreation(beanName);  
  35.         }  
  36.         bean=getObjectForBeanInstance(prototypeInstance,name, beanName, mbd);  
  37. }  

        繼續看createBean(…),可以看到在AbstractBeanFactory中它只是個抽象類,具體的實現交給其子類(又見模板模式),進入子類AbstractAutowireCapableBeanFactory中看createBean的具體實現:

[java] view plaincopy
 
  1. Object beanInstance = doCreateBean(beanName, mbd, args);  

 

        其具體的實現轉到doCreateBean(String…),這里我們看到與依賴注入關系比較密切的方法有createBeanInstance和populateBean。

[java] view plaincopy
 
  1. BeanWrapper instanceWrapper = null;  
  2. if (mbd.isSingleton()) {  
  3.     instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
  4. }  
  5. if (instanceWrapper == null) {  
  6.     instanceWrapper = createBeanInstance(beanName, mbd, args);  
  7. }  

 

[java] view plaincopy
 
  1. // Initialize the bean instance.  
  2. Object exposedObject = bean;  
  3. try {  
  4.     populateBean(beanName, mbd, instanceWrapper);  
  5.     if (exposedObject != null) {  
  6.         exposedObject = initializeBean(beanName, exposedObject, mbd);  
  7.     }  
  8. }  

        在createBeanInstance中生成了Bean所包含的Java對象,這個對象的生成有很多不同的方式,可以通過工廠方法生成,也可以通過容器的autowire特性生成,生成的方式由相關聯的BeanDefinition來指定,進入createBeanInstance方法,有:

[java] view plaincopy
 
  1. return instantiateUsingFactoryMethod(beanName, mbd, args);  

 

[java] view plaincopy
 
  1. return instantiateBean(beanName, mbd);  

 

        上面是其中的兩個實例化方法,上面的是在BeanDefinition的FactoryMethod存在的情況下,使用工廠方法對bean進行實例化。下面一個是使用默認的構造函數對bean進行實例化。我們進入instantiateBean(beanName,mbd),可以看到有:

[java] view plaincopy
 
  1. return getInstantiationStrategy().instantiate(mbd, beanName, parent);  

 

        因為getInstantiationStrategy()返回的默認的實例化策略,而默認的實例化策略是CglibSubclassingInstantiationStrategy,也即用cglib來對bean進行實例化。CGLIB是一個常用的字節碼生成器的類庫,它提供了一系列的API來提供Java的字節碼生成和轉換功能。

        我們再次回到doCreateBean()中的populateBean方法,看看在實例化Bean對象生成的基礎上,spring怎樣把這些bean對象的依賴關系設置好,完成整個依賴注入過程。在populateBean中,先是取得在BeanDefinition中設置的property值,這些property來自對BeanDefinition的解析,接著便開始進行依賴注入過程:

[java] view plaincopy
 
  1. //開始進行依賴注入過程,先處理autowire的注入  
  2. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  3.             MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
  4.   
  5.             //根據bean的名字進行autowire過程  
  6.             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
  7.                 autowireByName(beanName, mbd, bw, newPvs);  
  8.             }  
  9.   
  10.             //根據類型type進行autowire的過程  
  11.             if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  12.                 autowireByType(beanName, mbd, bw, newPvs);  
  13.             }  
  14.   
  15.             pvs = newPvs;  
  16. }  

         最后在通過applyPropertyValues對屬性進行注入:

[java] view plaincopy
 
  1. applyPropertyValues(beanName, mbd, bw, pvs);  

 

         接著我們到applyPropertyValues中去看具體的對屬性進行解析然后注入的過程,在其中會調用BeanDefinitionValueResolver對BeanDefinition進行解析,

 

[java] view plaincopy
 
  1. BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);  

 

         接著為解析值創建一個拷貝,拷貝的數據將會被注入到bean中,它會先對PropertyValue判斷,如果其沒有經過轉換則會調用resolveValueIfNecessary進行解析,然后注入到property中。下面到BeanDefinitionValueResolver中去看一下解析過程的實現,在函數resolveValueIfNecessary中包含了所有對注入類型的處理,以RuntimeBeanReference(其是在對BeanDefinition進行解析時生成的數據對象)為例:

 

[java] view plaincopy
 
  1. if (value instanceof RuntimeBeanReference) {  
  2.     RuntimeBeanReference ref = (RuntimeBeanReference) value;  
  3.     return resolveReference(argName, ref);  
  4. }  
  5. //當注入類型為RuntimeBeanReference時,進入resolveReference(…):  
  6. private Object resolveReference(Object argName, RuntimeBeanReference ref) {  
  7.         try {  
  8.             //從RuntimeBeanReference取得reference的名字  
  9.             String refName = ref.getBeanName();  
  10.             refName = String.valueOf(evaluate(refName));  
  11.             //如果ref是在雙親的IOC容器中,那就到雙親IOC容器中去取  
  12.             if (ref.isToParent()) {  
  13.                 if (this.beanFactory.getParentBeanFactory() == null) {  
  14.                     //拋出異常BeanCreationException  
  15.                                              ……  
  16.                 }  
  17.                 return this.beanFactory.getParentBeanFactory().  
  18.                                      getBean(refName);  
  19.             }  
  20.             else {  
  21.                                     //在當前IOC容器中去取bean  
  22.                 Object bean = this.beanFactory.getBean(refName);  
  23.                                 this.beanFactory.registerDependentBean(refName, this.beanName);  
  24.                 return bean;  
  25.             }  
  26. }  

        在上面的實現中,無論是到雙親的IOC容器中去取,還是在當前IOC容器中取,都會觸發一個getBean的過程,這就觸發了相應的依賴注入的發生。

 

        這就完成了resolve的過程,為依賴注入準備好了條件。但真正的把Bean對象設置到它所依賴的另一個Bean的屬性中去的地方是在BeanWrapper的setPropertyValues中(在分析populateBean的時候有提到),其中處理的屬性是各種各樣的。setPropertyValues的具體實現是在BeanWrapper的子類BeanWrapperImpl中:

        在doCreateBean中執行完populateBean,完成Bean的生成和依賴注入以后,開始對Bean進行初始化,這個初始化過程包含了對后置處理器的postProcessBeforeInitializtion回調,具體實現在initializeBean方法中:

[java] view plaincopy
 
  1. Object wrappedBean = bean;  
  2. if (mbd == null || !mbd.isSynthetic()) {  
  3.     wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
  4. }  
  5.   
  6. try {  
  7.     invokeInitMethods(beanName, wrappedBean, mbd);  
  8. }  
  9. catch (Throwable ex) {  
  10.     //拋出異常BeanCreationException  
  11. }  
  12.   
  13. if (mbd == null || !mbd.isSynthetic()) {  
  14.     wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
  15. }  
  16. return wrappedBean;  

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品久久久久久亚洲精品| 亚洲欧美另类自拍| 久久精品国产99国产精品澳门| 欧美性受xxx| 国产一区深夜福利| 91亚洲国产成人久久精品网站| 国产日韩在线看片| 欧美另类精品xxxx孕妇| 国产ts人妖一区二区三区| 成人免费视频在线观看超级碰| 日韩国产高清污视频在线观看| 久久亚洲一区二区三区四区五区高| 亚洲天堂av图片| 欧美日韩成人网| 亚洲国产精品成人va在线观看| 91国产中文字幕| 亚洲аv电影天堂网| 97人人爽人人喊人人模波多| 成人福利在线观看| 亚洲人成在线免费观看| 精品美女永久免费视频| 久久视频在线视频| 欧美视频在线免费看| 亚洲精品www久久久| 欧美激情乱人伦| 欧美亚洲国产成人精品| 丝袜美腿精品国产二区| 国产小视频91| 色婷婷综合久久久久中文字幕1| 久久久久久久久久国产精品| 国产一区玩具在线观看| 精品爽片免费看久久| 国产精品99久久久久久白浆小说| 最近2019年中文视频免费在线观看| 91精品成人久久| 久久久久亚洲精品成人网小说| 国产精品稀缺呦系列在线| 久久久综合免费视频| 亚洲欧美国产精品专区久久| 国产在线观看精品| 亚洲视频在线观看视频| 亚洲激情成人网| 亚洲视频网站在线观看| 最近中文字幕2019免费| 国产69精品久久久久久| 大荫蒂欧美视频另类xxxx| 91精品久久久久久久久久久久久久| 91精品国产自产在线老师啪| 欧美激情性做爰免费视频| 欧美性猛交xxxx乱大交极品| 日韩大片免费观看视频播放| 国产欧亚日韩视频| 日韩在线视频一区| 久久人人爽人人爽爽久久| 欧美日韩国产中字| 91国产精品91| 91成人在线观看国产| 亚洲片国产一区一级在线观看| 欧美怡春院一区二区三区| 在线观看精品自拍私拍| 久久久亚洲天堂| 国产成人综合精品在线| 国产精品第一视频| 国产精品网站入口| 亚洲美女性视频| 日韩欧美国产视频| 欧美精品激情在线观看| 粉嫩av一区二区三区免费野| 91tv亚洲精品香蕉国产一区7ujn| 亚洲va久久久噜噜噜久久天堂| 成人黄色片网站| 国产精品草莓在线免费观看| 日韩国产一区三区| 91成人福利在线| 日韩精品在线观看一区二区| 亚洲精品丝袜日韩| 在线观看日韩专区| 亚洲视频日韩精品| 日韩成人中文电影| 91精品视频免费| 欧美国产精品日韩| 欧美成人午夜视频| 日韩欧美国产高清91| 亚洲一区二区三区视频播放| 成人黄色免费网站在线观看| 日韩一级裸体免费视频| 欧美精品18videos性欧美| 欧美中文在线字幕| 国产成人一区二区三区| 欧美裸体男粗大视频在线观看| 欧美视频裸体精品| 亚洲图片欧美日产| 精品亚洲一区二区三区在线观看| 日韩电影免费在线观看中文字幕| 永久免费精品影视网站| 精品美女国产在线| 欧美黑人极品猛少妇色xxxxx| 亚洲色图50p| 91系列在线播放| 91免费在线视频网站| 日韩在线视频一区| 欧美风情在线观看| 欧美人交a欧美精品| 国产精品久久久久久中文字| 久久久久久国产精品美女| 久久综合亚洲社区| 日本国产精品视频| 欧美人成在线视频| 91亚洲人电影| 日韩中文字幕网站| 亚洲免费电影一区| 97在线视频免费播放| 欧美成人黄色小视频| 日本久久亚洲电影| 成人精品一区二区三区| 成人美女av在线直播| 亚洲视频在线观看网站| 久久久久久久影视| 日韩欧美综合在线视频| 亚洲精品自拍偷拍| 中文字幕日韩在线视频| 国产一区二区三区精品久久久| 亚洲精品综合精品自拍| 一本色道久久综合狠狠躁篇怎么玩| 亚洲图片欧美午夜| 欧美最猛性xxxxx亚洲精品| 亚洲国产日韩欧美在线动漫| 欧美视频在线视频| 不卡av在线播放| 亚洲成人a级网| 亚洲国产成人久久| 亚洲伊人一本大道中文字幕| 久久久国产91| 久久综合免费视频| 久久久久久中文| 日韩成人在线视频观看| 国产精品亚洲аv天堂网| 久久久国产成人精品| 国内精品久久久久久| 欧美一区二区.| 日日狠狠久久偷偷四色综合免费| 91久久夜色精品国产网站| 91香蕉国产在线观看| 日韩精品中文字幕在线观看| 色偷偷av一区二区三区| 国外视频精品毛片| 亚洲国产天堂久久综合网| 久久久综合免费视频| 成人信息集中地欧美| 欧美日韩免费网站| 操日韩av在线电影| 精品国产乱码久久久久久虫虫漫画| 成人做爰www免费看视频网站| 一区二区三区久久精品| 日韩亚洲在线观看| 欧美电影免费在线观看| 亚洲国语精品自产拍在线观看| 亚洲精品美女在线观看播放| 色久欧美在线视频观看| 欧美激情欧美激情在线五月| 久久这里有精品| 国产精品视频区1| 日韩av在线免费| 欧美乱妇高清无乱码|