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

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

(spring-第10回【IoC基礎篇】)InstantiationStrategy--實例化Bean的第三大利器

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

Bean的實例化整個過程如下圖:

其中,BeanDefinition加入到注冊表中,并由BeanFactoryPostPRocessor的實現類處理后,需要由InstantiationStrategy負責實例化。實例化僅僅是調用構造函數,相當于new了一個對象而已,bean的具體的屬性在此時并未賦值(當然,一開始在xml中配置了Bean屬性的值,或者在構造函數中有賦值語句的話,相關屬性才會在實例化的時候便有了值。)。InstantiationStrategy負責由Bean類的默認構造函數、帶參構造函數或者工廠方法等來實例化Bean。下面是Instantiation

Strategy的繼承結構(注意下面是父類,上面是子類,實線是繼承,虛線是實現):

InstantiationStrategy只是一個策略性的接口。

SimpleInstantiationStrategy是InstantiationStrategy的實現類,該類是一個簡單的用于Bean實例化的類,比如,由Bean類的默認構造函數、帶參構造函數或者工廠方法等來實例化Bean。從上圖中可以看出,該類有一個instantiationWithMethodInjection方法,但是實際上這只是個鉤子(hook),并非真正支持方法注入功能。

方法注入:在大部分情況下,容器中的bean都是singleton類型的(默認),單例類型是指spring只會實例化一次bean,并將bean放到緩沖池中,把bean的引用(地址)返回給調用者。如果一個singleton bean要引用另外一個singleton bean,或者一個prototype的bean引用另外一個prototype的bean時,通常情況下將一個bean定義為另一個bean的property值就可以了。就像下面這樣:

<bean id="boss" class="com.baobaotao.attr.Boss">        <property name="car">            <ref parent="car" />        </property>    </bean>

 

不過對于具有不同生命周期的bean來說這樣做就會有問題了,比如在調用一個singleton類型bean A的某個方法時,需要引用另一個prototype類型(每次調用都會重新實例化bean)的bean B,對于bean A來說,容器只會創建一次,這樣就沒法在需要的時候每次讓容器為bean A提供一個新的的bean B實例。也就是說,每次調用A時,我需要一個重新實例化的B。而由于A只會實例化一次,并且B是隨著A的實例化而實例化的,導致我得到的B也是沒有再次實例化的。這個時候就要使用方法注入。舉個簡單例子:

1 <bean id="car" class="com.baobaotao.injectfun.Car" 2         p:brand="紅旗CA72" p:price="2000" scope="prototype"/>3 4   <bean id="magicBoss" class="com.baobaotao.injectfun.MagicBoss" >5     <lookup-method name="getCar" bean="car"/>6   </bean>

使用lookup-method標簽,這樣,每次實例化magicBoss時就會加載它的getCar方法,如下:

public interface MagicBoss {   Car getCar(); }

由于lookup-method里面定義了bean="car",spring會自動實例化car。相當于在getCar()里面寫了一個實例化car的方法。

 

真正支持方法注入功能的是SimpleInstantiationStrategy的繼承類:CglibSubclassingInstantiationStrategy。它繼承了SimpleInstantiationStrategy并覆蓋了instantiationWithMethodInjection方法。不過使用這個方法必須用到cglib 類庫。它利用cglib為bean動態生成子類,這個類叫代理類,在子類中生成方法注入的邏輯,然后使用這個動態生成的子類創建bean的實例。(具體了解該技術,請學習spring的AOP,面向切面編程。后面章節我會詳細講到)。

 

下面大概看一下默認調用的SimpleInstantiationStrategy的instantiate方法:

 1 public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) { 2         // Don't override the class with CGLIB if no overrides. 3         if (beanDefinition.getMethodOverrides().isEmpty()) { 4             Constructor<?> constructorToUse; 5             synchronized (beanDefinition.constructorArgumentLock) { 6                 constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod; 7                 if (constructorToUse == null) { 8                     final Class clazz = beanDefinition.getBeanClass(); 9                     if (clazz.isInterface()) {10                         throw new BeanInstantiationException(clazz, "Specified class is an interface");11                     }12                     try {13                         if (System.getSecurityManager() != null) {14                             constructorToUse = accessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {15                                 public Constructor run() throws Exception {16                                     return clazz.getDeclaredConstructor((Class[]) null);17                                 }18                             });19                         }20                         else {21                             constructorToUse =    clazz.getDeclaredConstructor((Class[]) null);22                         }23                         beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;24                     }25                     catch (Exception ex) {26                         throw new BeanInstantiationException(clazz, "No default constructor found", ex);27                     }28                 }29             }30             return BeanUtils.instantiateClass(constructorToUse);31         }32         else {33             // Must generate CGLIB subclass.34             return instantiateWithMethodInjection(beanDefinition, beanName, owner);35         }36     }

由于前期帖不會過多去講源碼,所以只是大概了解一下,從第7行和第21行可以看出:如果bean沒有自己的構造函數,那么使用反射機制調用默認的無參構造函數去實例化bean。最后,30行,拿到這個構造函數,執行BeanUtils.instantiateClass方法。下面是該方法:

 1 public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException { 2         Assert.notNull(ctor, "Constructor must not be null"); 3         try { 4             ReflectionUtils.makeAccessible(ctor); 5             return ctor.newInstance(args); 6         } 7         catch (InstantiationException ex) { 8             throw new BeanInstantiationException(ctor.getDeclaringClass(), 9                     "Is it an abstract class?", ex);10         }11         catch (IllegalAccessException ex) {12             throw new BeanInstantiationException(ctor.getDeclaringClass(),13                     "Is the constructor accessible?", ex);14         }15         catch (IllegalArgumentException ex) {16             throw new BeanInstantiationException(ctor.getDeclaringClass(),17                     "Illegal arguments for constructor", ex);18         }19         catch (InvocationTargetException ex) {20             throw new BeanInstantiationException(ctor.getDeclaringClass(),21                     "Constructor threw exception", ex.getTargetException());22         }23     }

第四行和第五行就是創建實例了(首先需要把得到的構造函數強設為可訪問)。

 

由InstantiationStrategy實例化的bean只是相當于生成了一個新對象,具體的屬性賦值工作還要由BeanWrapper結合屬性編輯器來完成。BeanWrapper和屬性編輯器將會在接下來的博文中詳細介紹。

 

 

          學而不知道,與不學同;知而不能行,與不知同。

                                ——黃睎


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲午夜激情免费视频| 欧美成人网在线| 欧美情侣性视频| 色黄久久久久久| 麻豆乱码国产一区二区三区| 国产精品视频资源| 成人网在线免费看| 5566日本婷婷色中文字幕97| 中文字幕免费精品一区高清| 成人夜晚看av| 精品国产老师黑色丝袜高跟鞋| 国产一区红桃视频| 疯狂欧美牲乱大交777| 亚洲在线免费观看| 国产999精品| 精品国产乱码久久久久久天美| 久久综合久久美利坚合众国| 亚洲天堂av女优| 欧美自拍视频在线观看| 亚洲精品视频播放| 亚洲国产另类 国产精品国产免费| 国产丝袜一区二区| 精品国产91久久久久久老师| 欧美日韩在线免费观看| 午夜精品久久久久久99热| 国产aaa精品| 欧美美女18p| 性金发美女69hd大尺寸| 97视频色精品| 日韩欧美在线观看视频| 久久久久久香蕉网| 亚洲人成啪啪网站| 一本一本久久a久久精品牛牛影视| 成人深夜直播免费观看| 91久久精品在线| 亚洲欧美日韩一区在线| 日韩在线视频播放| 国产91精品网站| 91理论片午午论夜理片久久| 青草青草久热精品视频在线网站| 亚洲欧洲日产国产网站| 亚洲成人1234| 久久久久免费精品国产| 成人免费视频97| 91精品国产777在线观看| 一区二区成人av| 69久久夜色精品国产69| 欧美极品少妇全裸体| 欧美日韩国产一区在线| 欧美香蕉大胸在线视频观看| 欧美大全免费观看电视剧大泉洋| 在线日韩欧美视频| 日韩av免费网站| 国产91精品最新在线播放| 久久91亚洲精品中文字幕| 国产欧美精品一区二区三区-老狼| 91天堂在线观看| 国产亚洲一区二区精品| 中文字幕日韩在线播放| 黑人极品videos精品欧美裸| 国产精品网站大全| 亚洲欧美日韩在线一区| 日韩av电影免费观看高清| 狠狠躁夜夜躁人人爽天天天天97| 国产视频精品自拍| 国产精品免费久久久| 91精品国产网站| 日韩免费在线播放| 欧美激情中文网| 97国产成人精品视频| 精品久久久久久中文字幕大豆网| 欧美一区视频在线| 精品福利在线看| 欧美理论在线观看| 97香蕉久久夜色精品国产| 亲子乱一区二区三区电影| 欧美亚洲国产日韩2020| 91手机视频在线观看| 国产一区二区三区日韩欧美| 亚洲成人亚洲激情| 福利视频第一区| 色阁综合伊人av| 国产精品爽爽爽爽爽爽在线观看| 51久久精品夜色国产麻豆| 色综合亚洲精品激情狠狠| 亚洲桃花岛网站| 久久久97精品| 久久久久久亚洲精品中文字幕| 欧美三级免费观看| 欧美极品在线播放| 日韩美女视频在线观看| 日韩经典中文字幕| 国产成人aa精品一区在线播放| 国产精品va在线播放我和闺蜜| 欧美一区二区.| 中文字幕无线精品亚洲乱码一区| 久久免费视频网站| 日韩视频―中文字幕| 97在线日本国产| 久久精品国产视频| 色吧影院999| 北条麻妃一区二区三区中文字幕| 992tv在线成人免费观看| 亚洲成年人在线| 日韩中文字幕在线精品| 国产97在线|亚洲| 这里只有精品在线播放| 亚洲欧美一区二区三区情侣bbw| 按摩亚洲人久久| 亚洲欧美日韩国产精品| 欧美性视频在线| 欧美劲爆第一页| 福利二区91精品bt7086| 久久在精品线影院精品国产| 色爱精品视频一区| 亚洲三级av在线| 日本中文字幕成人| 国产视频精品在线| 有码中文亚洲精品| 欧美做爰性生交视频| 91精品综合久久久久久五月天| 欧美精品激情blacked18| 欧美激情第1页| 亚洲精品视频免费| 国产成人一区二区三区小说| 国产丝袜一区视频在线观看| 欧美激情视频一区二区三区不卡| 欧美猛男性生活免费| 中文字幕亚洲欧美在线| 成人黄色大片在线免费观看| 国产欧美在线看| 亚洲一区二区三区视频播放| 亚洲а∨天堂久久精品喷水| 91av视频在线免费观看| 国产精品成人一区二区| 91免费综合在线| 亚洲欧美激情在线视频| 最近2019年中文视频免费在线观看| 久久精品影视伊人网| 亚洲第一视频在线观看| 91精品国产综合久久久久久久久| 亚洲自拍偷拍一区| 92国产精品久久久久首页| 亚洲精品一区中文| 欧美黑人国产人伦爽爽爽| 国产精品久久久久久搜索| 欧美性xxxx极品高清hd直播| 欧美性xxxx18| 国产欧美在线观看| 亚洲美女av黄| 精品国产精品三级精品av网址| 欧美国产亚洲精品久久久8v| 亚洲激情视频网站| 国产视频精品久久久| 日韩精品视频在线播放| 亚洲欧洲国产精品| 国产精品美腿一区在线看| 日韩欧美国产激情| 国产精品久久999| 国产精品99久久久久久www| 亚洲第一中文字幕在线观看| 91久久夜色精品国产网站| 在线日韩中文字幕| 国产视频久久久久久久|