為了保持項(xiàng)目風(fēng)格統(tǒng)一,省的有些理論派挑刺,還是延續(xù)字段注入的操作。
某個(gè)業(yè)務(wù)場(chǎng)景下,有一個(gè)抽象的父類和多個(gè)具體的子類,子類中需要用到父類注入的對(duì)象。
當(dāng)即有人就說,這么寫:
public abstract class AbstractClass{
@Autowired
protected InjectedBean injectedBean;
}
it works!
但是我們看到為了只讓子類使用該對(duì)象,我們使用了protected
訪問修飾符,但這意味著,子類也可以set該對(duì)象一個(gè)新的值?;A(chǔ)知識(shí)。
哦,改進(jìn)一下唄
public abstract class AbstractClass{
@Autowired
protected final InjectedBean injectedBean;
}
final加持,完美的解決了問題。很可惜,不可以。
為什么呢?
Having @Autowired and final on a field are contradictory.
The latter says: this variable has one and only one value, and it's initialized at construction time.
The former says: Spring will construct the object, leaving this field as null (its default value). Then Spring will use reflection to initialize this field with a bean of type WorkspaceRepository.
If you want final fields autowired, use constructor injection
ref: https://stackoverflow.com/questions/34580033/spring-io-autowired-the-blank-final-field-may-not-have-been-initialized
簡(jiǎn)單來說,就是二者賦值的時(shí)機(jī)不統(tǒng)一造成了互斥。
那我們使用上面提到的,通constructor injection
注入試試
public abstract class AbstractClass{
private InjectedBean injectedBean;
@Autowired
public void AbstractClass(InjectedBean injectedBean) {
this.injectedBean = injectedBean;
}
}
Spring 不會(huì)在抽象類的構(gòu)造函數(shù)上解析 @Autowired 注解??梢酝ㄟ^子類的構(gòu)造函數(shù)注入實(shí)現(xiàn)。
public abstract class AbstractClass{
private InjectedBean injectedBean;
public void AbstractClass(InjectedBean injectedBean) {
this.injectedBean = injectedBean;
}
}
public class ChildClass{
private InjectedBean injectedBean;
@Autowired
public void ChildClass(InjectedBean injectedBean) {
super(injectedBean);
}
}
這么寫真的有些繁瑣了...而且,就我的項(xiàng)目而言,我的初衷是給子類使用,這么豈不是多此一舉。
好的,也就引出了Setter注入。
public abstract class AbstractClass{
private LogRepository logRepository;
@Autowired
public final void setLogRepository(LogRepository logRepository) {
this.logRepository = logRepository;
}
}
Setter的時(shí)候,標(biāo)記為public final
。
Getter的時(shí)候,標(biāo)記為protected
。
可以說是最佳實(shí)踐了。
ref: https://segmentfault.com/a/1190000039053805
事實(shí)上,當(dāng)你使用IDE開發(fā)的時(shí)候,你使用了Spring的字段注入,你會(huì)得到一個(gè)提示:
Field injection is not recommended
當(dāng)然是因?yàn)檫@種方式有好多缺點(diǎn):
不允許不可變字段的聲明,像我們剛才說的@Autowired protected final
代碼壞味道的潛在根源
因?yàn)樽侄巫⑷胧侨绱说姆奖?,你可以“只要需要”就注入一個(gè)你想操作的對(duì)象,結(jié)果不知不覺中注入了十幾個(gè)甚至幾十個(gè)(見賢思齊,我所在的項(xiàng)目中確實(shí)已經(jīng)有這樣的問題了)。
反之,如果我們通過構(gòu)造函數(shù)注入,隨著注入對(duì)象的增多,構(gòu)造函數(shù)的參數(shù)不斷變多,你明顯的就能聞到“壞味道”了,這時(shí)候你得開始想,是時(shí)候把當(dāng)前類重新劃分了,怎么能承擔(dān)如此多的職責(zé)呢?職責(zé)單一忘了嗎?SOLID天天盯著你們哪!
和Spring的容器緊耦合
如果這點(diǎn)你不覺得有什么,那你是不是忘記寫單元測(cè)試了?
單元測(cè)試的時(shí)候你也引入了Spring框架?就是為了使用“注入”這個(gè)功能?
如果我們使用構(gòu)造函數(shù)注入,或者Setter注入,我們?cè)诿撾xSpring框架之后(比如單元測(cè)試)的時(shí)候,我們可以通過其他方式傳入目標(biāo)對(duì)象。反之,我們只能強(qiáng)依賴Spring框架了。
隱藏了依賴
當(dāng)使用依賴項(xiàng)注入模式時(shí),受影響的類應(yīng)該通過公開構(gòu)造函數(shù)中所需的依賴項(xiàng)或使用方法(setter)的可選依賴項(xiàng),使用公共接口清楚地公開這些依賴項(xiàng)。當(dāng)使用基于字段的依賴項(xiàng)注入時(shí),類本質(zhì)上是向外部世界隱藏這些依賴項(xiàng)。
ref: https://blog.marcnuri.com/field-injection-is-not-recommended
文章題目:Abstract類中使用@Autowire-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://chinadenli.net/article12/dhgdgc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、靜態(tài)網(wǎng)站、定制開發(fā)、域名注冊(cè)、面包屑導(dǎo)航、虛擬主機(jī)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容