Abstract類中使用@Autowire-創(chuàng)新互聯(lián)

背景

項目使用的就是SpringBoot默認的結(jié)構(gòu),我看了下,依賴注入使用了最不推薦的字段注入。Abstract類中使用@Aut
owire

字段注入

為了保持項目風格統(tǒng)一,省的有些理論派挑刺,還是延續(xù)字段注入的操作。
某個業(yè)務(wù)場景下,有一個抽象的父類和多個具體的子類,子類中需要用到父類注入的對象。
當即有人就說,這么寫:

創(chuàng)新互聯(lián)公司是一家專注于網(wǎng)站設(shè)計、成都網(wǎng)站制作與策劃設(shè)計,拜城網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:拜城等地區(qū)。拜城做網(wǎng)站價格咨詢:18980820575
public abstract class AbstractClass{
    @Autowired
    protected InjectedBean injectedBean;
}

it works!
但是我們看到為了只讓子類使用該對象,我們使用了protected訪問修飾符,但這意味著,子類也可以set該對象一個新的值?;A(chǔ)知識。
哦,改進一下唄

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

簡單來說,就是二者賦值的時機不統(tǒng)一造成了互斥。

構(gòu)造函數(shù)注入

那我們使用上面提到的,通constructor injection注入試試

public abstract class AbstractClass{
    private InjectedBean injectedBean;

    @Autowired
    public void AbstractClass(InjectedBean injectedBean) {
        this.injectedBean = injectedBean;
    }
}

Spring 不會在抽象類的構(gòu)造函數(shù)上解析 @Autowired 注解??梢酝ㄟ^子類的構(gòu)造函數(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);
    }
}

這么寫真的有些繁瑣了...而且,就我的項目而言,我的初衷是給子類使用,這么豈不是多此一舉。
好的,也就引出了Setter注入。

Setter注入

public abstract class AbstractClass{
    private LogRepository logRepository;
    @Autowired
    public final void setLogRepository(LogRepository logRepository) {
        this.logRepository = logRepository;
    }
}

Setter的時候,標記為public final。
Getter的時候,標記為protected

可以說是最佳實踐了。

ref: https://segmentfault.com/a/1190000039053805

為什么不推薦使用字段注入?

事實上,當你使用IDE開發(fā)的時候,你使用了Spring的字段注入,你會得到一個提示:

Field injection is not recommended

當然是因為這種方式有好多缺點:

  1. 不允許不可變字段的聲明,像我們剛才說的@Autowired protected final

  2. 代碼壞味道的潛在根源
    因為字段注入是如此的方便,你可以“只要需要”就注入一個你想操作的對象,結(jié)果不知不覺中注入了十幾個甚至幾十個(見賢思齊,我所在的項目中確實已經(jīng)有這樣的問題了)。
    反之,如果我們通過構(gòu)造函數(shù)注入,隨著注入對象的增多,構(gòu)造函數(shù)的參數(shù)不斷變多,你明顯的就能聞到“壞味道”了,這時候你得開始想,是時候把當前類重新劃分了,怎么能承擔如此多的職責呢?職責單一忘了嗎?SOLID天天盯著你們哪!

  3. 和Spring的容器緊耦合
    如果這點你不覺得有什么,那你是不是忘記寫單元測試了?
    單元測試的時候你也引入了Spring框架?就是為了使用“注入”這個功能?
    如果我們使用構(gòu)造函數(shù)注入,或者Setter注入,我們在脫離Spring框架之后(比如單元測試)的時候,我們可以通過其他方式傳入目標對象。反之,我們只能強依賴Spring框架了。

  4. 隱藏了依賴
    當使用依賴項注入模式時,受影響的類應該通過公開構(gòu)造函數(shù)中所需的依賴項或使用方法(setter)的可選依賴項,使用公共接口清楚地公開這些依賴項。當使用基于字段的依賴項注入時,類本質(zhì)上是向外部世界隱藏這些依賴項。

ref: https://blog.marcnuri.com/field-injection-is-not-recommended

文章題目:Abstract類中使用@Autowire-創(chuàng)新互聯(lián)
網(wǎng)頁網(wǎng)址:http://muchs.cn/article12/dhgdgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、靜態(tài)網(wǎng)站定制開發(fā)、域名注冊、面包屑導航、虛擬主機

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)