<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    J2EE之巔

     

    依賴注入(Dependency Injection)模式的特點(diǎn)分析與實(shí)現(xiàn)

    依賴注入(Dependency Injection模式的特點(diǎn)分析與實(shí)現(xiàn)

    ――構(gòu)造子注入Constructor Injection模式的分析與實(shí)現(xiàn)

     

     

     

    chaocai2001@yahoo.com.cn

     

    摘要:本文對(duì)IoC模式、依賴注入(Dependency Injection) 模式做了簡(jiǎn)要介紹,文中分析構(gòu)造子注入模式與其他模式相比較的優(yōu)勢(shì)和特點(diǎn),并給出了在JAVA中實(shí)現(xiàn)該模式的方法。

     

     

    1         引言

    IoCInversion of Control)模式以被目前的輕量級(jí)容器所廣泛應(yīng)用,通過(guò)IoC模式這些容器幫助開(kāi)發(fā)者將來(lái)自不同項(xiàng)目的組件裝配成一個(gè)內(nèi)聚的應(yīng)用程序。輕量級(jí)的IoC容器(如Spring、pico-container)雖然為我們的開(kāi)發(fā)提供了很大的便利,但是在很多情況下這些輕量級(jí)容器所提供的功能并不一定非常適合我們的需要,也許這些容器的功能過(guò)于龐大了,或者所提供的功能缺乏對(duì)特定應(yīng)用的針對(duì)性,或者我們需要更高的運(yùn)行效率,這時(shí)我們可以在了解IoC的原理的基礎(chǔ)上利用JAVA的反射機(jī)制自己實(shí)現(xiàn)靈活的、可擴(kuò)展的組件機(jī)制。

    2         IoC與依賴注入(Dependency Injection)模式簡(jiǎn)介

    GoF的設(shè)計(jì)模式相同,IoC模式同樣是關(guān)注重用性,但與GoF模式不同的是IoC模式更加關(guān)注二進(jìn)制級(jí)的重用性和可擴(kuò)展性,即可以直接通過(guò)二進(jìn)制級(jí)進(jìn)行擴(kuò)充,復(fù)用的模塊通常被稱(chēng)為組件或者插件,組件和插件都是在運(yùn)行時(shí)進(jìn)行裝載的。

    GoF的設(shè)計(jì)模式中我們大量看到的是面向接口編程:Interface Driven Design 接口驅(qū)動(dòng),接口驅(qū)動(dòng)有很多好處,可以提供不同靈活的子類(lèi)實(shí)現(xiàn),增加代碼穩(wěn)定和健壯性等等,但是接口一定是需要實(shí)現(xiàn)的,也就是如下語(yǔ)句遲早要執(zhí)行:

    AInterface a = new AInterfaceImp();

    由于以上的代碼被寫(xiě)入了調(diào)用者程序中,同時(shí)象AinterfaceImp這樣的接口的實(shí)現(xiàn)類(lèi)是在編譯時(shí)被裝載的,如果以后想加入新的接口實(shí)現(xiàn)類(lèi)則必須修改調(diào)用者的代碼。

    IoC模式與以上情況不同,接口的實(shí)現(xiàn)類(lèi)是在運(yùn)行時(shí)被裝載的,這樣即使以后新添加了接口實(shí)現(xiàn)類(lèi)是也不需修改調(diào)用者的代碼(可以通過(guò)特定的方式來(lái)定位新增的實(shí)現(xiàn)類(lèi),如配置文件指定)。IoC英文為 Inversion of Control,即反轉(zhuǎn)模式,這里有著名的好萊塢理論:你呆著別動(dòng),到時(shí)我會(huì)找你。

    IoC模式可以延緩接口的實(shí)現(xiàn),根據(jù)需要實(shí)現(xiàn),有個(gè)比喻:接口如同空的模型套,在必要時(shí),需要向模型套注射石膏,這樣才能成為一個(gè)模型實(shí)體,因此,對(duì)于這些新生的容器,它們反轉(zhuǎn)的是“如何定位插件的具體實(shí)現(xiàn)”。因此, Martin Fowler 給這種模式起了一個(gè)形象的名稱(chēng)“依賴注入”Dependency Injection。

    圖表 1 采用Dependency Injection前后的依賴關(guān)系變化

    依賴注入的形式主要有三種,分別將它們叫做構(gòu)造子注入(Constructor Injection)、設(shè)值方法注入(Setter Injection)和接口注入(Interface Injection)。

    這三種方式在Martin Fowler的《Inversion of Control Containers and the Dependency Injection pattern》中都給出了詳細(xì)的定義及說(shuō)明,本文就不再贅述了,下面的內(nèi)容將著重介紹構(gòu)造子注入模式的特點(diǎn)及實(shí)現(xiàn)方法。

    3         構(gòu)造子注入模式的特點(diǎn)及實(shí)現(xiàn)

    3.1      構(gòu)造子注入模式的特點(diǎn)

    通常情況下設(shè)方法注入和接口注入較易于被開(kāi)發(fā)人員接受,而構(gòu)造子注入則應(yīng)用較少,實(shí)際上構(gòu)造子注入具有很多其他兩者所不具有的優(yōu)勢(shì):

    1 構(gòu)造子注入形成了一種更強(qiáng)的依賴契約

    2 可以獲得更加簡(jiǎn)明的代碼

    3 更加簡(jiǎn)明的依賴聲明機(jī)制,無(wú)須定義XML配置文件或設(shè)方法

    4 更加符合接口與實(shí)現(xiàn)分離的組件特征,組件接口表明能夠向其它組件提供的服務(wù),而實(shí)現(xiàn)則應(yīng)該是所提供服務(wù)的實(shí)現(xiàn)應(yīng)該與服務(wù)契約無(wú)關(guān)(即不應(yīng)包含用于獲得依賴的設(shè)值方法等)。

    5 不會(huì)出現(xiàn)不確定的狀態(tài)。在設(shè)值方法注入中,由于并不是所有的設(shè)值方法(setter)都一定會(huì)被調(diào)用的,所以會(huì)有不確定狀態(tài)。

    從以上幾點(diǎn)我們還可以分析出構(gòu)造子注入對(duì)于組件代碼的入侵性遠(yuǎn)小于其它兩種模式(接口注入使得組件必須實(shí)現(xiàn)特定接口,設(shè)值方法同樣要求組件提供特定的setter方法),代碼更加易于維護(hù)

    圖表 2 示例中類(lèi)的關(guān)系

    Client的實(shí)現(xiàn)依賴于接口A、BC的實(shí)現(xiàn),但是為了提供系統(tǒng)更好的靈活性和可擴(kuò)展性,各接口的實(shí)現(xiàn)以組件的方式利用java的反射機(jī)制進(jìn)行運(yùn)行時(shí)裝載,注意到組件間可能會(huì)存在某種依賴關(guān)系,例如組件AX依賴與接口B的實(shí)現(xiàn)類(lèi),而這中依賴關(guān)系必須在運(yùn)行時(shí)動(dòng)態(tài)注入,組件為了告訴組件的調(diào)用者這種依賴關(guān)系以便注入,可以使用上文提到的各種模式:

    1 使用接口注入模式

    public interface InjectB{

           public void injectB(B bImp);

    }

    public interface InjectC{

           public void injectC(C cImp);

    }

    public class AImp implements A,InjectB,InjectC{

          

           public void injectB(B bImp);

           public void injectC(C cImp);

          

    }

    2 使用設(shè)值注入模式

    public class AImp implements A {

          

           public void setB(B bImp);

           public void setC(C cImp);

          

    }

     

    3 使用構(gòu)造子注入模式

    public class AImp implements A {

          

           public AImp(B bImp, C cImp){

                 

           }

          

    }

    由以上實(shí)例可以清楚的看出采用構(gòu)造子注入模式的實(shí)現(xiàn)組件代碼最為簡(jiǎn)單,且所受的入侵性最小。

    3.2      JAVA中實(shí)現(xiàn)構(gòu)造子注入模式

    java.NET這樣具有反射功能的語(yǔ)言中實(shí)現(xiàn)類(lèi)型的運(yùn)行時(shí)載入并不復(fù)雜,只要通過(guò)Class.forName或生成自己的ClassLoader就可以實(shí)現(xiàn)。

    同樣我們可以通過(guò)反射機(jī)制獲取組件構(gòu)造函數(shù)的參數(shù),注入相應(yīng)接口的實(shí)現(xiàn),作者將此過(guò)程進(jìn)行了封裝,以下是代碼:

    public class RefectHelper {

             public Object ConstructorHelper(String className,ConstructorParamDeal pd) throws Exception{

                       try{

                                //獲取類(lèi)中的構(gòu)造函數(shù)

    Constructor[] constructs=Class.forName(className).getConstructors();              //實(shí)現(xiàn)中默認(rèn)使用第一個(gè)構(gòu)造函數(shù)類(lèi)創(chuàng)建實(shí)例      

                                Class [] classes=constructs[0].getParameterTypes();                  

                                  //獲取要注入的參數(shù)實(shí)例

                                Object []obj=pd.dealParam(classes);

                                //創(chuàng)建實(shí)例

                                return constructs[0].newInstance(obj);

                       }catch(Exception e){

                                throw e;

                       }

                      

                      

             }

    }

    /**

    *構(gòu)造函數(shù)參數(shù)注入

    **/

    public interface ConstructorParamDeal {

             /**

             *根據(jù)構(gòu)造函數(shù)中參數(shù)的類(lèi)型注入,相應(yīng)的實(shí)現(xiàn)

             @param classes 構(gòu)造函數(shù)的參數(shù)類(lèi)型

             return 注入構(gòu)造函數(shù)的參數(shù)實(shí)現(xiàn)

             **/

             public Object [] dealParam(Class [] classes);

    }

    public class ParamDeal implements ConstructorParamDeal{

     

             /* (non-Javadoc)

              * @see com.topsec.tsm.agent.helper.ConstructorParamDeal#dealParam(java.lang.Class[])

              */

             public Object [] dealParam(Class[] classes) {

                       Object [] obj=new Object[classes.length];

                       for (int i=0;i<obj.length;i++){

                                //為不同類(lèi)型注入選擇不同實(shí)例

                                if (classes[i].equals(String.class)){

                                         obj[i]=”Hello World”;                                       

                                }

                       }

                       return obj;

             }

     

    }

    上面的程序中ConstructorHelper用于利用反射機(jī)制枚舉出載入類(lèi)的構(gòu)造函數(shù)及構(gòu)造函數(shù)的參數(shù)的類(lèi)型,至于不同類(lèi)型注入什么樣的實(shí)例則由ContructorParamDeal的實(shí)現(xiàn)者來(lái)決定,ContructorParamDeal的實(shí)現(xiàn)者同樣可以以組件的形式在運(yùn)行時(shí)動(dòng)態(tài)載入。由于組件間的依賴關(guān)系的制約,所以組件實(shí)例化的順序需要特別考慮。

    4         結(jié)束語(yǔ)

    三種依賴注入模式各有其特點(diǎn)和優(yōu)勢(shì),只有充分理解這些模式間的不同,才能為自己的應(yīng)用選擇正確的依賴注入模式,文中介紹的構(gòu)造子注入模式實(shí)現(xiàn)方法,在使用其他具有反射功能的語(yǔ)言(如:.NET)時(shí)同樣可以參考。

     

     

     

     [參考文獻(xiàn)]

    1 Martin Fowler,Inversion of Control Containers and the Dependency Injection pattern,http://www.martinfowler.com/articles/injection.html,2004

    2 Erich Gamma,Design Patterns,Addison Wesley,1999

    3 http://www.picocontainer.org/

    4 彭晨陽(yáng),Ioc模式, http://www.jdon.com,2004

    posted on 2006-03-14 08:52 超越巔峰 閱讀(7970) 評(píng)論(1)  編輯  收藏

    評(píng)論

    # re: 依賴注入(Dependency Injection)模式的特點(diǎn)分析與實(shí)現(xiàn) 2010-06-22 10:43 愛(ài)之谷

    三種依賴注入模式各有其特點(diǎn)和優(yōu)勢(shì),只有充分理解這些模式間的不同,才能為自己的應(yīng)用選擇正確的依賴注入模式,文中介紹的構(gòu)造子注入模式實(shí)現(xiàn)方法,在使用其他具有反射功能的語(yǔ)言(如:.NET)時(shí)同樣可以參考。  回復(fù)  更多評(píng)論   


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(12)

    隨筆分類(lèi)(54)

    隨筆檔案(59)

    文章分類(lèi)(2)

    文章檔案(1)

    相冊(cè)

    搜索

    積分與排名

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 免费成人在线电影| 亚洲国产精品无码久久一线| 精品在线免费观看| 亚洲国产成人AV网站| 亚洲乱码一二三四区麻豆| 国产亚洲精品va在线| 亚洲高清成人一区二区三区| 最新猫咪www免费人成| 91视频免费网址| 国产免费无码一区二区| CAOPORM国产精品视频免费| 亚洲Aⅴ在线无码播放毛片一线天 亚洲avav天堂av在线网毛片 | 久久久久免费看黄a级试看| 一级做a爰片久久毛片免费看 | 国产乱子伦精品免费视频| 亚洲国产日韩a在线播放| 亚洲国产精品久久人人爱| 亚洲av午夜福利精品一区| 亚洲最大AV网站在线观看| 亚洲 无码 在线 专区| 国产jizzjizz视频全部免费| 成年女人男人免费视频播放| 成年网站免费视频A在线双飞| 91精品免费久久久久久久久| 久久福利青草精品资源站免费| 久久精品成人免费国产片小草| 一级特黄a大片免费| 人人爽人人爽人人片A免费| 男性gay黄免费网站| 真人无码作爱免费视频| 麻豆亚洲AV成人无码久久精品| 亚洲精品国产第一综合99久久| 亚洲日韩乱码中文字幕| 亚洲国产精品无码中文lv| 亚洲欧美中文日韩视频| 亚洲国产成人无码AV在线影院| 亚洲成a∧人片在线观看无码| 国产精品久久久久久亚洲小说| 综合一区自拍亚洲综合图区| 国产亚洲福利一区二区免费看| 曰批免费视频播放在线看片二|