Spring框架的依賴注入和控制反轉
依賴注入(dependency inject)
依賴是開發中不可缺少的場景,每一個業務需求都需要多個類都實體相互依賴完成,但是物件之間的依賴卻給開發帶來了很多不便,因此提出了注入的概念。
舉個例子:
public class Soldier {
public void shot(){
System.out.println("soldier shot!");
}
}
Knight有一個方法attack,要完成這個舉動必須要soldier來進行,也就是Knight依賴Soldier,所以這裡兩個類就緊耦合在一起。
所以Knight的attack就受到了Soldier的限制了,那依賴注入怎麼解決?
1.把Soldier定義為一個介面
2.通過Knight的構造器注入Soldier的具體物件
3.對於Knight而言,無需關注Soldier具體是實現類,只需要在attack時呼叫soldier進行shot即可
public class Knight {
private Soldier soldier;
public Knight(Soldier soldier) {
this.soldier = soldier;
}
public void attack(){
soldier.shot();
}
}
public interface Soldier {
public void shot();
}
public class Navy implements Soldier {
@Override
public void shot() {
System.out.println("navy attack!");
}
}
public class AirForce implements Soldier {
@Override
public void shot() {
System.out.println("AirForce is attacking!");
}
}
public class Knight {
private Soldier soldier;
public Knight() {
soldier = new Soldier();
}
public void attack(){
soldier.shot();
}
}
依賴注入往往和控制反轉(Inversion of Control)說到一起,控制反轉指物件的控制權、生命週期等行為不再由客戶端(呼叫方)來控制,而是由IoC容器來控制,呼叫方不再需要關心他要呼叫的物件如何產生,只要告訴容器,我要用某個物件了,由容器來提供。
傳統的程式設計方式,在物件需要另一個物件時,都是主動來建立物件,控制物件都行為,因此這種通過容器來提供物件都建立和銷燬都方式,形象的成為控制反轉。
Spring框架通過Ioc這種設計思想,將所有的類都註冊到容器中,告訴容器:
1.A是什麼類
2.A需要哪些類(依賴)
有了這兩個資訊,在程式執行的時候,容器就會在適當的時候把依賴的類注入到A中,對A來說,以前是他控制這些依賴類,現在就是統一由Spring容器來提供,這種控制的行為就被反轉了。
依賴注入是基於java的反射機制實現的,java提供了反射機制,在程式執行中,就可以通過反射得到一個類的全部屬性和方法,並且可以呼叫,Spring就可以通過xml或者註解等方式,得到交給容器控制的所有類的依賴關係,在程式執行過程中進行建立,並且可以執行這些類的行為。