在IDEA升級2017版后闲礼,發(fā)現(xiàn)以前使用的 @Autowired 出現(xiàn)了個警告 Field injection is not recommended
@Autowired的三種使用方式
@Controller
public class Controller{
? ??//通過構(gòu)造器注入
? ? private final DependencyA dependencyA;
????private final DependencyB dependencyB;
? ? @Autowired
? ? public Controller(DependencyA dependencyA,DependencyB dependencyB){
? ? ? ? this.dependencyA = dependencyA;
????????this.dependencyB = dependencyB;
? ? }
? ? //通過set方法注入
? ?private DependencyA dependencyA;????
????private DependencyB dependencyB;?
? ? @Autowired
? ? public void setDependencyA(DependencyA dependencyA){
? ? ? ? this.dependencyA = dependencyA;
? ? }
????@Autowired
????public void setDependencyB(DependencyB dependencyB){? ? ? ? ? ? ??
????????this.dependencyB = dependencyB;? ??
????}? ?
? ? //通過field注入
? ? @Autowired
? ? private DependencyA dependencyA;
? ? @Autowired
????private DependencyB dependencyB;?
}
單一職責(zé)原則
當(dāng)你使用構(gòu)造器方式注入,構(gòu)造器參數(shù)的數(shù)量就會變得太多以至于很容易出現(xiàn)錯誤袱衷。擁有太多的依賴通常意味著你的類要承擔(dān)更多的責(zé)任鲸匿,明顯違背了單一職責(zé)原則和關(guān)注點分離缤剧,這是一個很好的現(xiàn)象,表明該類需要進(jìn)一步檢查和重構(gòu)。在直接注入filed時屡立,沒有這樣的危險信號,因為這種方法可以無限擴(kuò)展搀军。
依賴隱藏
使用DI容器意味著類不再對依賴負(fù)責(zé)膨俐,獲取依賴的職責(zé)從類中抽離出來,DI容器會幫你裝配罩句,當(dāng)類不再負(fù)責(zé)獲取依賴時焚刺,它應(yīng)該使用方法或構(gòu)造器去了解類本身需要什么,以及它是可選的(setter方法)還是強(qiáng)制的(構(gòu)造器)门烂。
DI Container Coupling
One of the core ideas of the DI frameworks is that the managed class should have no dependency on the DI container used. In other words, it should be just a plain POJO, which can be instantiated independently, provided you pass it all the required dependencies. This way you can instantiate it in a unit test without starting the DI container and test it separately (with a container that would be more of integration test). If there is no container coupling, you can use the class either as managed or non-managed or even switch to a new DI framework.
對上面英文段的解釋:
受DI容器管理的類只是一個普通的java對象乳愉,是能夠被獨立實例化的。通過這種方式屯远,可以在單元測試中實例化它蔓姚,而不需要啟動DI容器去實例化它。如果沒有DI容器耦合慨丐,不管有沒有被DI容器管理赂乐,都可以實例化這個類,甚至切換到新的DI框架咖气。簡而言之挨措,就是可以脫離spring的管理去操作這個類挖滤。
有一種方式(調(diào)用默認(rèn)構(gòu)造器)來創(chuàng)建對象就是使用new關(guān)鍵字,但是當(dāng)這個對象缺少一些必要的依賴浅役,調(diào)用的時候就會出現(xiàn)空指針異常斩松。
這樣的類不能在DI容器(測試、其他模塊)之外重用觉既,因為除了反射之外惧盹,沒有其他方法向它提供所需的依賴項。
舉個例子:
public class DependencyA {
? ? public void a(){
? ? ? ? System.out.println("dependencyA");
? ? }
}
public class POJO {
? ? @Autowired
? ? private DependencyA dependencyA;
? ? public void execute(){
? ? ? ? dependencyA.a();
? ? }
}
public class Test {
? ? public static void main(String[] args) {
? ? ? ? POJO pojo = new POJO();
? ? ? ? pojo.execute();
? ? }
}
當(dāng)你執(zhí)行execute()方法時就會報空指針異常瞪讼,是因為DependencyA沒有被創(chuàng)建钧椰,使用這種方式(@Autowired)也不會強(qiáng)制你去創(chuàng)建類所需的依賴,所以當(dāng)使用者調(diào)用的方法的時候就可能會出現(xiàn)空指針異常符欠。
不變性
與構(gòu)造函數(shù)不同嫡霞,字段注入不能用于向final字段指定依賴,從而有效地實現(xiàn)可變的對象希柿。
Setters
setter注入適合于可選依賴項
Constructors
構(gòu)造函數(shù)注入適合于強(qiáng)制依賴
結(jié)論:
Field注入應(yīng)該盡可能地去避免使用诊沪,構(gòu)造器注入更適合強(qiáng)制性的注入旨在不變性,Setter注入更適合可變性的注入曾撤。