在使用IDEA 進(jìn)行Spring 開(kāi)發(fā)的時(shí)候,在字段上面使用@Autowired注解的時(shí)候,IDEA 會(huì)有警告提示:
翻譯過(guò)來(lái)就是這個(gè)意思:不建議使用基于 field 的注入方式。
Spring 開(kāi)發(fā)團(tuán)隊(duì)建議:在Spring Bean 永遠(yuǎn)使用基于constructor 的方式進(jìn)行依賴(lài)注入。對(duì)于必須的依賴(lài),永遠(yuǎn)使用斷言來(lái)確認(rèn)。
為什么Spring 團(tuán)隊(duì)會(huì)提出這樣的建議?直接使用這種基于 field 的注入方式有什么問(wèn)題?
首先需要知道,Spring 中有這么3種依賴(lài)注入的方式 :
- 基于 field 注入(屬性注入)
- 基于 setter 注入
- 基于 constructor 注入(構(gòu)造器注入)
1. 基于 field 注入
所謂基于 field 注入,就是在bean的變量上使用注解進(jìn)行依賴(lài)注入。本質(zhì)上是通過(guò)反射的方式直接注入到field,所以private的成員也可以被注入具體的對(duì)象。這是平常開(kāi)發(fā)中看的最多也是最熟悉的一種方式,同時(shí),也正是 Spring 團(tuán)隊(duì)所不推薦的方式。比如:
@Autowired
private Svc svc;
2. 基于 setter 方法注入
通過(guò)對(duì)應(yīng)變量的setXXX()方法以及在方法上面使用注解,來(lái)完成依賴(lài)注入。比如:
private Helper helper;
@Autowired
public void setHelper(Helper helper) {
this.helper = helper;
}
注:在 Spring 4.3 及以后的版本中,setter 上面的 @Autowired 注解是可以不寫(xiě)的。
3. 基于 constructor 注入
將各個(gè)必需的依賴(lài)全部放在帶有注解構(gòu)造方法的參數(shù)中,并在構(gòu)造方法中完成對(duì)應(yīng)變量的初始化,這種方式,就是基于構(gòu)造方法的注入,也是日常最為推薦的一種使用方式。這種注入方式很直接,通過(guò)對(duì)象構(gòu)建的時(shí)候建立關(guān)系,所以這種方式對(duì)對(duì)象創(chuàng)建的順序會(huì)有要求,當(dāng)然Spring會(huì)搞定這樣的先后順序,除非出現(xiàn)循環(huán)依賴(lài),然后就會(huì)拋出異常。比如:
private final Svc svc;
@Autowired
public HelpService(@Qualifier("svcB") Svc svc) {
this.svc = svc;
}
在 Spring 4.3 及以后的版本中,如果這個(gè)類(lèi)只有一個(gè)構(gòu)造方法,那么這個(gè)構(gòu)造方法上面也可以不寫(xiě) @Autowired 注解。
Spring 開(kāi)發(fā)團(tuán)隊(duì)的建議
- 強(qiáng)制依賴(lài)就用構(gòu)造器方式
- 可選、可變的依賴(lài)就用setter 注入當(dāng)然可以在同一個(gè)類(lèi)中使用這兩種方法。構(gòu)造器注入更適合強(qiáng)制性的注入旨在不變性,Setter注入更適合可變性的注入。
Spring 團(tuán)隊(duì)提倡使用基于構(gòu)造方法的注入,因?yàn)檫@樣一方面可以將依賴(lài)注入到一個(gè)不可變的變量中 (注:final 修飾的變量) ,另一方面也可以保證這些變量的值不會(huì)是 null 。此外,經(jīng)過(guò)構(gòu)造方法完成依賴(lài)注入的組件 (注:比如各個(gè) service),在被調(diào)用時(shí)可以保證它們都完全準(zhǔn)備好了 。與此同時(shí),從代碼質(zhì)量的角度來(lái)看,一個(gè)巨大的構(gòu)造方法通常代表著出現(xiàn)了代碼異味,這個(gè)類(lèi)可能承擔(dān)了過(guò)多的責(zé)任 。
基于 setter 的注入,則只應(yīng)該被用于注入非必需的依賴(lài),同時(shí)在類(lèi)中應(yīng)該對(duì)這個(gè)依賴(lài)提供一個(gè)合理的默認(rèn)值。如果使用 setter 注入必需的依賴(lài),那么將會(huì)有過(guò)多的 null 檢查充斥在代碼中。使用 setter 注入的一個(gè)優(yōu)點(diǎn)是,這個(gè)依賴(lài)可以很方便的被改變或者重新注入 。






