同一接口不同實現的注入需要先明白依賴倒置的意思。
定義:高層模塊不應該依賴低層模塊,二者都應該依賴其抽象;抽象不應該依賴細節;細節應該依賴抽象。
問題由來:類A直接依賴類B,假如要將類A改爲依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責複雜的業務邏輯;類B和類C是低層模塊,負責基本的原子操作;假如修改類A,會給程序帶來不必要的風險。
解決方案:將類A修改爲依賴接口I,類B和類C各自實現接口I,類A通過接口I間接與類B或者類C發生聯繫,則會大大降低修改類A的機率。
依賴倒置原則基於這樣一個事實:相對於細節的多變性,抽象的東西要穩定的多。以抽象爲基礎搭建起來的架構比以細節爲基礎搭建起來的架構要穩定的多。在java中,抽象指的是接口或者抽象類,細節就是具體的實現類,使用接口或者抽象類的目的是制定好規範和契約,而不去涉及任何具體的操作,把展現細節的任務交給他們的實現類去完成。
依賴倒置原則的核心思想是面向接口編程
接口編程的優勢之一,就是可以同時編程
傳遞依賴關係有三種方式,以上的例子中使用的方法是接口傳遞,另外還有兩種傳遞方式:構造方法傳遞和setter方法傳遞,相信用過Spring框架的,對依賴的傳遞方式一定不會陌生。
在實際編程中,我們一般需要做到如下3點:
- 低層模塊儘量都要有抽象類或接口,或者兩者都有。
- 變量的聲明類型儘量是抽象類或接口。
- 使用繼承時遵循里氏替換原則。
依賴倒置原則的核心就是要我們面向接口編程,理解了面向接口編程,也就理解了依賴倒置。
在spring中注入同一接口不同的實現
spring中有幾個註解需要清楚
- @AutoWired 標註屬性,此註解是byType 按照類型注入,找到一個成功,找到多個異常
- @Service(“XXXX”) 標註類,表明此類交由spring來管理,可以在其他地方使用了,括號中的名稱可有可無
- @Qualifier(“XXXX”) 標註屬性,按照名稱注入,在spring這個桶中找到一個成功,找到多個失敗,缺省是駝峯法,
- @Resource(name = “XXXX”) 標註屬性,等同於1+3的註解,名稱與類型必須同時滿足。
HelloWorldController.java中注入
@Resource(name = "helloo")
private Hello hello;
@Resource(name = "hellot")
private Hello hellot;
@RequestMapping("/hellow")
@ResponseBody
public String getHello() {
System.out.println("service is running");
hello.read();
hellot.read();
return "hello world";
}
其中helloo是第一個實現 hellot是第二個實現兩者的類型都是Hello的interface
Hello.java的接口
public interface Hello {
void read();
}
HelloServiceImpl.java的接口 第一個實現helloo
@Service("helloo")
public class HelloServiceImpl implements Hello {
@Override
public void read() {
System.out.println("this is hello");
}
}
HelloServiceImpl.java的接口 第二個實現hellot
@Service("hellot")
public class HelloServiceImpl3 implements Hello{
@Override
public void read() {
System.out.println("this is helloservice3333");
}
}
啓動項目,請求/hellow講可以看到
面向接口開發,
- 可以將速度提升至最好,也是敏捷開發的基礎,
- 依賴倒置,將越底層的包裝越嚴密,類間的互相依賴組合等等統統用抽象來表示,即使底層更改邏輯,不用大費周章,耦合降至最低。
…