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