1. 程式人生 > >Spring基礎(4)——設值注入、構造注入

Spring基礎(4)——設值注入、構造注入

設值注入:

也稱屬性注入,是指通過setter()方法傳入被呼叫者的例項。這種注入方式簡單、直觀,在Spring依賴注入中也是最常用的。

public interface Animal {
    public void eatFood();
}
public interface Action {
    public void eat();
}
public class Cat implement Animal {
    private Action action;
    public Cat() {}
    public void setAction(Action action) {
        this.action = action;
    }
    public void eatFood() {
        System.out.println(action.eat());
    }
}
public class CatAction implement Action {
    public CatAction(){}
    public String eat() {
        return "貓吃魚";
    }
}

採用Spring配置檔案將Animal例項與Action例項組織起來:

bean.xml:Spring配置檔案

<beans>
    <bean id="cat" class="Cat">
        <property name="action">
            <ref local="catAction"><!-- 將兩一個Bean的引用注入給cat bean-->
        </property>
    </bean>
    <bean id="catAction" class="CatAction">
</beans>

配置檔案的Bean的class不能僅僅是介面,而必須是真正的實現類。介面是不能被直接例項化的,只能例項化該介面的實現類。

Spring會自動接管每個Bean定義裡面的<property>元素定義。Spring會在執行無參構造器後、建立預設的Bean的例項後,呼叫相應的setter()方法為程式注入屬性值。property定義的屬性值將不在由該Bean來主動建立和管理,而改為被動接受Spring注入。

每個Bean的id屬性是該Bean的唯一標識,程式通過id屬性訪問Bean,bean與bean的依賴關係也通過Id屬性建立。

public static void main(String[] args) {
    ApplicationContext ctx = new FileSystemXmlApplicationContext("bean.xml");
    Animal animal = (Animal)ctx.getBean("cat");
    cat.eatFood();
}

呼叫者無需瞭解被呼叫者的實現過程,連工廠定位都可以聖羅。如果需要改寫Action的實現類或者說需要提供給Animal另一個Action的實現類,Animal介面和Cat實現類都無需修改,只需要提供Action的另一個實現,然後通過配置檔案進行簡單修改即可。

Animal和Action之間沒有任何的程式碼耦合,Bean和Bean之間的依賴關係交由Spring進行管理,採用Setter方法為目標Bean注入屬性的方式成為設值注入。業務物件的變換變得簡單,物件與物件之間的依賴關係從程式碼裡分離出來,通過配置檔案動態管理。

構造注入:

指通過構造方法完成依賴關係的設定,而不是通過setter()方法。

public class Dog implement Animal {
    private Action action;
    public Dog(){}
    public Dog(Action action) {
        this.action = action;
    }
    public void eatFood() {
        System.out.pringln(this.action.eat());
    }
}
<beans>
    <bean id="dog" class="Dog">
        <constructor-arg><ref bean="dogAction" /></constructor-arg>
    </bean>
</beans>

執行效果與設值注入相同,區別在於建立Animal例項時,action屬性賦值的時機不同,設值注入需要某一個bean例項時建立一個預設的bean的例項,然後呼叫相應的設值方法,注入依賴關係。而構造注入則是在建立bean例項時,已經完成依賴關係的注入。

優缺點:

設值注入:與傳統Javabean的寫法更加相近,開發人員更容易理解和接受,通過setter()方法射釘起來關係顯得更加直觀和自然。    對於複雜的依賴關係,如果採用構造注入,會導致構造器過於臃腫,難以閱讀,Spring在建立Bean例項時,需要同時例項化期以來的全部例項,因而導致效能下降。而是用設值注入則能避免這些問題。    尤其是在某些屬性可選的情況下,多引數的構造器更加笨重。

構造注入:可以再構造器中決定依賴關係的注入順序。對於依賴關係無需變化的bean,構造注入更有用。因為沒有setter()方法,所有的依賴關係全部在構造器內設定,因此,無須擔心後續的程式碼對依賴關係產生破壞。依賴關係只能在構造器內設定,則只有元件的建立者才能改變元件的依賴關係。對元件的呼叫者而言,元件內部的依賴關係完全透明,更符合高內聚的原則。建議採用設定注入為主,構造注入為輔的注入策略。對於依賴關係無需變化的注入,儘量採用構造注入;而對於其他的依賴關係的注入,則考慮採用設值注入。