北大青鳥IT教育博客

           

          JAVA框架當(dāng)中Spring的依賴注入和控制反轉(zhuǎn)

          Spring的核心機(jī)制依賴注入簡(jiǎn)介
            Spring能有效地組織J2EE應(yīng)用各層的對(duì)象。不管是控制層的Action對(duì)象,還是業(yè)務(wù)層的Service對(duì)象,還是持久層的DAO對(duì)象,都可在 Spring的治理下有機(jī)地協(xié)調(diào)、運(yùn)行。Spring將各層的對(duì)象以松耦合的方式組織在一起,Action對(duì)象無須關(guān)心Service對(duì)象的具體實(shí)現(xiàn),Service對(duì)象無須關(guān)心持久層對(duì)象的具體實(shí)現(xiàn),各層對(duì)象的調(diào)用完全面向接口。當(dāng)系統(tǒng)需要重構(gòu)時(shí),代碼的改寫量將大大減少。
            上面所說的一切都得宜于Spring的核心機(jī)制,依靠注入。依靠注入讓bean與bean之間以配置文件組織在一起,而不是以硬編碼的方式耦合在一起。

            依靠注入(Dependency Injection)和控制反轉(zhuǎn)(Inversion of Control)是同一個(gè)概念。具體含義是:當(dāng)某個(gè)角色(可能是一個(gè)Java實(shí)例,調(diào)用者)需要另一個(gè)角色(另一個(gè)Java實(shí)例,被調(diào)用者)的協(xié)助時(shí),在傳統(tǒng)的程序設(shè)計(jì)過程中,通常由調(diào)用者來創(chuàng)建被調(diào)用者的實(shí)例。但在Spring里,創(chuàng)建被調(diào)用者的工作不再由調(diào)用者來完成,因此稱為控制反轉(zhuǎn);創(chuàng)建被調(diào)用者實(shí)例的工作通常由Spring容器來完成,然后注入調(diào)用者,因此也稱為依靠注入。
            不管是依靠注入,還是控制反轉(zhuǎn),都說明Spring采用動(dòng)態(tài)、靈活的方式來治理各種對(duì)象。對(duì)象與對(duì)象之間的具體實(shí)現(xiàn)互相透明。在理解依靠注入之前,看如下這個(gè)問題在各種社會(huì)形態(tài)里如何解決:一個(gè)人(Java實(shí)例,調(diào)用者)需要一把斧子(Java實(shí)例,被調(diào)用者)。
            (1)原始社會(huì)里,幾乎沒有社會(huì)分工。需要斧子的人(調(diào)用者)只能自己去磨一把斧子(被調(diào)用者)。對(duì)應(yīng)的情形為:Java程序里的調(diào)用者自己創(chuàng)建被調(diào)用者。
            (2)進(jìn)入工業(yè)社會(huì),工廠出現(xiàn)。斧子不再由普通人完成,而在工廠里被生產(chǎn)出來,此時(shí)需要斧子的人(調(diào)用者)找到工廠,購買斧子,無須關(guān)心斧子的制造過程。對(duì)應(yīng)Java程序的簡(jiǎn)單工廠的設(shè)計(jì)模式。
            (3)進(jìn)入“按需分配”社會(huì),需要斧子的人不需要找到工廠,坐在家里發(fā)出一個(gè)簡(jiǎn)單指令:需要斧子。斧子就自然出現(xiàn)在他面前。對(duì)應(yīng)Spring的依靠注入。
            第一種情況下,Java實(shí)例的調(diào)用者創(chuàng)建被調(diào)用的Java實(shí)例,必然要求被調(diào)用的Java類出現(xiàn)在調(diào)用者的代碼里。無法實(shí)現(xiàn)二者之間的松耦合。
            第二種情況下,調(diào)用者無須關(guān)心被調(diào)用者具體實(shí)現(xiàn)過程,只需要找到符合某種標(biāo)準(zhǔn)(接口)的實(shí)例,即可使用。此時(shí)調(diào)用的代碼面向接口編程,可以讓調(diào)用者和被調(diào)用者解耦,這也是工廠模式大量使用的原因。但調(diào)用者需要自己定位工廠,調(diào)用者與特定工廠耦合在一起。
            第三種情況下,調(diào)用者無須自己定位工廠,程序運(yùn)行到需要被調(diào)用者時(shí),系統(tǒng)自動(dòng)提供被調(diào)用者實(shí)例。事實(shí)上,調(diào)用者和被調(diào)用者都處于Spring的治理下,二者之間的依靠關(guān)系由Spring提供。
            所謂依靠注入,是指程序運(yùn)行過程中,假如需要調(diào)用另一個(gè)對(duì)象協(xié)助時(shí),無須在代碼中創(chuàng)建被調(diào)用者,而是依靠于外部的注入。Spring的依靠注入對(duì)調(diào)用者和被調(diào)用者幾乎沒有任何要求,完全支持對(duì)POJO之間依靠關(guān)系的治理。依靠注入通常有兩種:
            ·設(shè)值注入。
            ·構(gòu)造注入。 設(shè)值注入
            設(shè)值注入是指通過setter方法傳入被調(diào)用者的實(shí)例。這種注入方式簡(jiǎn)單、直觀,因而在Spring的依靠注入里大量使用。看下面代碼,是Person的接口
             //定義Person接口
            public interface Person
            {
             //Person接口里定義一個(gè)使用斧子的方法
             public void useAxe();
            }
            
            然后是Axe的接口
            
             //定義Axe接口
            
            public interface Axe
            {
             //Axe接口里有個(gè)砍的方法
             public void chop();
            }
            Person的實(shí)現(xiàn)類
            
             //Chinese實(shí)現(xiàn)Person接口
            
            public class Chinese implements Person
            {
             //面向Axe接口編程,而不是具體的實(shí)現(xiàn)類
             private Axe axe;
             //默認(rèn)的構(gòu)造器
             public Chinese()
             {}
             //設(shè)值注入所需的setter方法
             public void setAxe(Axe axe)
             {
            this.axe = axe;
             }
             //實(shí)現(xiàn)Person接口的useAxe方法
             public void useAxe()
             {
            System.out.println(axe.chop());
             }
            }
            Axe的第一個(gè)實(shí)現(xiàn)類
            
             //Axe的第一個(gè)實(shí)現(xiàn)類 StoneAxe
            
            public class StoneAxe implements Axe
            {
             //默認(rèn)構(gòu)造器
             public StoneAxe()
             {}
             //實(shí)現(xiàn)Axe接口的chop方法
             public String chop()
             {
            return "石斧砍柴好慢";
             }
            }
            下面采用Spring的配置文件將Person實(shí)例和Axe實(shí)例組織在一起。配置文件如下所示:
            
             <!-- 下面是標(biāo)準(zhǔn)的XML文件頭 -->
            <?xml version="1.0" encoding="gb2312"?>
            <!-- 下面一行定義Spring的XML配置文件的dtd -->
            "   <!-- 以上三行對(duì)所有的Spring配置文件都是相同的 -->
            <!-- Spring配置文件的根元素 -->
            <BEANS>
             <!—定義第一bean,該bean的id是chinese, class指定該bean實(shí)例的實(shí)現(xiàn)類 -->
             <BEAN class=lee.Chinese id=chinese>
             <!-- property元素用來指定需要容器注入的屬性,axe屬性需要容器注入此處是設(shè)值注入,因此Chinese類必須擁有setAxe方法 -->

          posted on 2009-05-12 16:39 武漢北大青鳥 閱讀(176) 評(píng)論(0)  編輯  收藏


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


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

          導(dǎo)航

          統(tǒng)計(jì)

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章檔案

          默認(rèn)

          搜索

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 池州市| 襄樊市| 邢台市| 武冈市| 特克斯县| 红河县| 周宁县| 永吉县| 商河县| 禄丰县| 宣武区| 蒲城县| 南皮县| 文安县| 车险| 苍溪县| 新野县| 高密市| 西乌珠穆沁旗| 孙吴县| 阿拉尔市| 新源县| 大邑县| 炎陵县| 资讯 | 陕西省| 青田县| 天峻县| 汝阳县| 麻栗坡县| 利辛县| 六枝特区| 景洪市| 太仆寺旗| 壤塘县| 崇文区| 嘉兴市| 项城市| 蓬溪县| 定结县| 石渠县|