文章出處

此篇文章,參考其他文章,親自測試,并附上測試代碼和測試結果圖,詳詳細細,明明白白的講解什么叫依賴注入,什么叫IOC,絕對能給你看完之后,就知道的清清楚楚,明明白白,在以后都不會忘記這個概念,當然你要是愿意拿我的代碼親自測試一下的話,效果會更好。畢竟我不是復制粘貼黨。

Spring 能有效地組織J2EE應用各層的對象。不管是控制層的Action對象,還是業務層的Service對象,還是持久層的DAO對象,都可在Spring的 管理下有機地協調、運行。Spring將各層的對象以松耦合的方式組織在一起,Action對象無須關心Service對象的具體實現,Service對 象無須關心持久層對象的具體實現,各層對象的調用完全面向接口。當系統需要重構時,代碼的改寫量將大大減少。

   上面所說的一切都得宜于Spring的核心機制,依賴注入。依賴注入讓bean與bean之間以配置文件組織在一起,而不是以硬編碼的方式耦合在一起。理解依賴注入。

   依賴注入(Dependency Injection)和控制反轉(Inversion of Control)是同一個概念。具體含義是:當某個角色(可能是一個Java實例,調用者)需要另一個角色(另一個Java實例,被調用者)的協助時,在傳統的程序設計過程中,通常由調用者來創建被調用者的實例。但在Spring里,創建被調用者的工作不再由調用者來完成,因此,稱為控制反轉;創建被調用者實例的工作通常由Spring容器來完成,然后注入調用者,因此也稱為依賴注入。

   不管是依賴注入,還是控制反轉,都說明Spring采用動態、靈活的方式來管理各種對象。對象與對象之間的具體實現互相透明。在理解依賴注入之前,看如下這個問題在各種社會形態里如何解決:一個人(Java實例,調用者)需要一把斧子(Java實例,被調用者)。

   (1)原始社會里,幾乎沒有社會分工。需要斧子的人(調用者)只能自己去磨一把斧子(被調用者)。對應的情形為:Java程序里的調用者自己創建被調用者。

   (2)進入工業社會,工廠出現。斧子不再由普通人完成,而在工廠里被生產出來,此時需要斧子的人(調用者)找到工廠,購買斧子,無須關心斧子的制造過程。對應Java程序的簡單工廠的設計模式。

   (3)進入“按需分配”社會,需要斧子的人不需要找到工廠,坐在家里發出一個簡單指令:需要斧子。斧子就自然出現在他面前。對應Spring的依賴注入。

   第一種情況下,Java實例的調用者創建被調用的Java實例,必然要求被調用的Java類出現在調用者的代碼里。無法實現二者之間的松耦合。

  第二種情況下,調用者無須關心被調用者具體實現過程,只需要找到符合某種標準(接口)的實例,即可使用。此時調用的代碼面向接口編程,可以讓調用者和被調用者解耦,這也是工廠模式大量使用的原因。但調用者需要自己定位工廠,調用者與特定工廠耦合在一起。

  第三種情況下,調用者無須自己定位工廠,程序運行到需要被調用者時,系統自動提供被調用者實例。事實上,調用者和被調用者都處于Spring的管理下,二者之間的依賴關系由Spring提供。

  所謂依賴注入,是指程序運行過程中,如果需要調用另一個對象協助時,無須在代碼中創建被調用者,而是依賴于外部的注入。
Spring的依賴注入對調用者和被調用者幾乎沒有任何要求,完全支持對POJO之間依賴關系的管理。依賴注入通常有兩種:

·設值注入。
·構造注入。

 

一、設值注入。
設值注入是指通過setter方法傳入被調用者的實例。這種注入方式簡單、直觀,因而在Spring的依賴注入里大量使用。
看下面代碼:

 

package com.fusionskye.ezsonar.model.configcenter;//上面的這個包名和配置文件里面的bean類的class屬性對應,要測試的話,自己修改成自己的import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;/** 定義Person接口 */interface Person {    void useAxe();  //Person接口里定義一個使用斧子的方法}/** 定義Axe(斧子英文Axe)接口 */interface Axe {    String chop(); //Axe接口里有個砍(chop)的方法,原作里面是void,但是這里應該是返回String類型}/** * Person的實現類 * Chinese實現Person接口 */class Chinese implements Person {    /** 面向Axe(斧子)接口編程,而不是具體的實現類 */    private Axe axe;    /** 默認的構造器 */    public Chinese() { }    /**     * 設值注入所需的setter方法     * 在xml配置文件中要用到此屬性,所以訪問權限要public,不能不寫     */    public void setAxe(Axe axe) { this.axe = axe; }    /** 實現Person接口的useAxe方法 */    public void useAxe() { System.out.println(axe.chop()); }}/** * Axe的第一個實現類 StoneAxe 石斧 */class StoneAxe implements Axe {    /** 默認構造器 */    StoneAxe() { }    /** 實現Axe接口的chop方法 */    public String chop() { return "石斧砍柴好慢"; }}/** * Axe的第二個實現類 SteelAxe 鋼斧 */class SteelAxe implements Axe{    /** 默認構造器 */    public SteelAxe() { }    /** 實現Axe接口的chop方法 */    @Override    public String chop() {        return "鋼斧砍柴真快";    }}/** * Created by lxk on 2016/9/14 */class Cmt {    /**     * 對上面的有的public權限控制給省略是因為只在一個包下使用,所以就使得權限變成了包內權限,然后就直接不寫     */    public static void main(String[] args) {        Chinese chinese = new Chinese();        StoneAxe stoneAxe = new StoneAxe();        //設值注入是指通過setter方法傳入被調用者的實例        //如上句的解釋:具體的斧子對象不是由人來初始化,而是如上所述的設值注入。        chinese.setAxe(stoneAxe);        //上面的Chinese和石斧都是我們自己new的,要是在Spring容器,就由容器來初始化.        chinese.useAxe();        System.out.println("---------下面是配置文件實現設置注入------------");        //因為是獨立的應用程序,顯式地實例化Spring的上下文。        ApplicationContext ctx = new FileSystemXmlApplicationContext("sss.xml");        //通過Person bean的id來獲取bean實例,面向接口編程,因此        //此處強制類型轉換為接口類型        Person p = (Person) ctx.getBean("chinese");        //直接執行Person的userAxe()方法。        p.useAxe();    }}
上面是Java的測試代碼,下面是對應的配置文件,sss.xml文件,具體內容如下:

 

 

                                                                    
我覺得本大師兄的注釋寫的以及非常詳細啦吧。

 

 

從配置文件中,可以看到Spring管理bean的靈巧性。bean與bean之間的依賴關系放在配置文件里組織,而不是寫在代碼里。通過配置文件的 指定,Spring能精確地為每個bean注入屬性。因此,配置文件里的bean的class元素,不能僅僅是接口,而必須是真正的實現類。

   Spring會自動接管每個bean定義里的property元素定義。Spring會在執行無參數的構造器后、創建默認的bean實例后,調用對應
的setter方法為程序注入屬性值。property定義的屬性值將不再由該bean來主動創建、管理,而改為被動接收Spring的注入。

   每個bean的id屬性是該bean的惟一標識,程序通過id屬性訪問bean,bean與bean的依賴關系也通過id屬性完成。

 

下面上測試的結果,如下:

第一張圖是,配置文件里面用的是石斧,代碼里面自己new Chinese和stoneAxe的對象測試設置注入的結果。

 

第二張圖,測試的結果,配置文件里面修改 使用鋼斧bean,上面的沒修改的執行結果,如下:

 

Person與Axe之間沒有任何代碼耦合關系,bean與bean之間的依賴關系由Spring管理。采用setter方法為目標bean注入屬性的方式,稱為設值注入。

   業務對象的更換變得相當簡單,對象與對象之間的依賴關系從代碼里分離出來,通過配置文件動態管理。

 

二、 構造注入


  所謂構造注入,指通過構造函數來完成依賴關系的設定,而不是通過setter方法。對前面代碼Chinese類做簡單的修改,修改后的代碼如下:

 

/** * Person的實現類 * Chinese實現Person接口 */class Chinese implements Person {    /** 面向Axe(斧子)接口編程,而不是具體的實現類 */    private Axe axe;    /** 默認的構造器 */    public Chinese() { }    /** 構造注入所需的帶參數的構造器 */    public Chinese(Axe axe) {        this.axe = axe;    }    /** 實現Person接口的useAxe方法 */    public void useAxe() { System.out.println(axe.chop()); }}

 

 

此時無須Chinese類里的setAxe方法,構造Person實例時,Spring為Person實例注入所依賴的Axe實例。
構造注入的配置文件也需做簡單的修改,修改后的配置文件如下:
        

 

執行效果與使用steelAxe設值注入時的執行效果完全一樣。

區別在于:創建Person實例中Axe屬性的時機不同——設值注入是現創建一個默認的bean實例,
然后調用對應的構造方法注入依賴關系。而構造注入則在創建bean實例時,已經完成了依賴關系的

就愛閱讀www.92to.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20161206/63584.html

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()