自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么官方不推薦使用 @Autowired?

開(kāi)發(fā) 前端
為什么?是 @Autowired 不行嗎?并不是。它可以用,但問(wèn)題是:它不是無(wú)敵的,濫用起來(lái)容易埋坑。下面就來(lái)聊聊為啥官方建議你慎用 @Autowired,順便再帶點(diǎn)代碼例子,希望對(duì)你會(huì)有所幫助。

前言

很多人剛接觸 Spring 的時(shí)候,對(duì) @Autowired 絕對(duì)是愛(ài)得深沉。

一個(gè)注解,輕松搞定依賴(lài)注入,連代碼量都省了。

誰(shuí)不愛(ài)呢?

但慢慢地,尤其是跑到稍微復(fù)雜點(diǎn)的項(xiàng)目里,@Autowired 就開(kāi)始給你整點(diǎn)幺蛾子。

于是,官方Spring 4.0開(kāi)始:不建議無(wú)腦用 @Autowired,而是更推薦構(gòu)造函數(shù)注入。

圖片圖片

為什么?

是 @Autowired 不行嗎?并不是。

它可以用,但問(wèn)題是:它不是無(wú)敵的,濫用起來(lái)容易埋坑。

下面就來(lái)聊聊為啥官方建議你慎用 @Autowired,順便再帶點(diǎn)代碼例子,希望對(duì)你會(huì)有所幫助。

1. 容易導(dǎo)致隱式依賴(lài)

很多小伙伴在工作中喜歡直接寫(xiě):

@Service
public class MyService {
    @Autowired
    private MyRepository myRepository;
}

看著挺簡(jiǎn)單,但問(wèn)題來(lái)了:類(lèi)的依賴(lài)關(guān)系藏得太深了。

  • 你看這段代碼,MyService 和 MyRepository 的關(guān)系其實(shí)是個(gè)“隱形依賴(lài)”,全靠 @Autowired 來(lái)注入。
  • 如果有個(gè)同事剛接手代碼,打開(kāi)一看,完全不知道 myRepository 是啥玩意兒、怎么來(lái)的,只有通過(guò) IDE 或運(yùn)行時(shí)才能猜出來(lái)。

隱式依賴(lài)的結(jié)果就是,代碼看起來(lái)簡(jiǎn)單,但維護(hù)起來(lái)費(fèi)勁。

后期加個(gè)新依賴(lài),或者改依賴(lài)順序,分分鐘把人搞糊涂。

怎么破?

用 構(gòu)造函數(shù)注入 替代。

@Service
public class MyService {
    private final MyRepository myRepository;

    // 構(gòu)造函數(shù)注入,依賴(lài)一目了然
    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }
}

這樣做的好處是:

  • 依賴(lài)清晰:誰(shuí)依賴(lài)誰(shuí),直接寫(xiě)在構(gòu)造函數(shù)里,明明白白。
  • 更易測(cè)試:構(gòu)造函數(shù)注入可以手動(dòng)傳入 mock 對(duì)象,方便寫(xiě)單元測(cè)試。

2. 會(huì)導(dǎo)致強(qiáng)耦合

再舉個(gè)例子,很多人喜歡直接用 @Autowired 注入具體實(shí)現(xiàn)類(lèi),比如:

@Service
public class MyService {
    @Autowired
    private SpecificRepository specificRepository;
}

表面上沒(méi)毛病,但這是硬邦邦地把 MyService 和 SpecificRepository 綁死了。

萬(wàn)一有一天,業(yè)務(wù)改了,需要切換成另一個(gè)實(shí)現(xiàn)類(lèi),比如 AnotherSpecificRepository,你得改代碼、改注解,連帶著測(cè)試也崩。

怎么破?

用接口和構(gòu)造函數(shù)注入,把依賴(lài)解耦。

@Service
public class MyService {
    private final Repository repository;

    public MyService(Repository repository) {
        this.repository = repository;
    }
}

然后通過(guò) Spring 的配置文件或者 @Configuration 類(lèi)配置具體實(shí)現(xiàn):

@Configuration
public class RepositoryConfig {
    @Bean
    public Repository repository() {
        return new SpecificRepository();
    }
}

這么搞的好處是:

  • 靈活切換:改實(shí)現(xiàn)類(lèi)時(shí),不用動(dòng)核心邏輯代碼。
  • 符合面向接口編程的思想:降低耦合,提升可擴(kuò)展性。

3. 容易導(dǎo)致 NullPointerException

有些小伙伴喜歡這么寫(xiě):

@Service
public class MyService {
    @Autowired
    private MyRepository myRepository;

    public void doSomething() {
        myRepository.save(); // 啪!NullPointerException
    }
}

問(wèn)題在哪?如果 Spring 容器還沒(méi)來(lái)得及注入依賴(lài),你的代碼就跑了(比如在構(gòu)造函數(shù)或初始化方法中直接調(diào)用依賴(lài)),結(jié)果自然就是 NullPointerException。

怎么破?

用構(gòu)造函數(shù)注入,徹底干掉 null 的可能性。

@Service
public class MyService {
    private final MyRepository myRepository;

    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository; // 確保依賴(lài)在對(duì)象初始化時(shí)就已注入
    }

    public void doSomething() {
        myRepository.save();
    }
}

構(gòu)造函數(shù)注入的另一個(gè)優(yōu)點(diǎn)是:依賴(lài)注入是強(qiáng)制的,Spring 容器不給你注入就報(bào)錯(cuò),讓問(wèn)題早暴露。

4.自動(dòng)裝配容易搞出迷惑行為

Spring 的自動(dòng)裝配機(jī)制有時(shí)候是“黑魔法”,尤其是當(dāng)你的項(xiàng)目里有多個(gè)候選 Bean 時(shí)。比如:

@Service
public class MyService {
    @Autowired
    private Repository repository; // 容器里有兩個(gè) Repository 實(shí)現(xiàn)類(lèi),咋辦?
}

如果有兩個(gè)實(shí)現(xiàn)類(lèi),比如 SpecificRepository 和 AnotherRepository,Spring 容器直接報(bào)錯(cuò)。解決方法有兩種:

  • 指定 @Primary。
  • 用 @Qualifier 手動(dòng)指定。

但這些方式都讓代碼看起來(lái)更復(fù)雜了,還可能踩坑。

怎么破?

構(gòu)造函數(shù)注入 + 顯式配置。

@Configuration
public class RepositoryConfig {
    @Bean
    public Repository repository() {
        return new SpecificRepository();
    }
}

你明確告訴 Spring 該用哪個(gè)實(shí)現(xiàn)類(lèi),別讓容器幫你猜,省得以后“配錯(cuò)藥”。

5. 寫(xiě)單元測(cè)試非常痛苦

最后,聊聊測(cè)試的事兒。

@Autowired 依賴(lài) Spring 容器才能工作,但寫(xiě)單元測(cè)試時(shí),大家都不想起 Spring 容器(麻煩、慢)。結(jié)果就是:

  • 字段注入:沒(méi)法手動(dòng)傳入 mock 對(duì)象。
  • 自動(dòng)裝配:有時(shí)候不清楚用的 Bean 是哪個(gè),測(cè)試難搞。

怎么破?

構(gòu)造函數(shù)注入天生就是為單元測(cè)試設(shè)計(jì)的。

public class MyServiceTest {
    @Test
    public void testDoSomething() {
        MyRepository mockRepository = mock(MyRepository.class);
        MyService myService = new MyService(mockRepository);

        // 測(cè)試邏輯
    }
}

看見(jiàn)沒(méi)?

直接傳入 mock 對(duì)象,測(cè)試簡(jiǎn)單、優(yōu)雅。

總結(jié)

簡(jiǎn)單總結(jié)下問(wèn)題:

  1. 隱式依賴(lài)讓代碼可讀性差。
  2. 強(qiáng)耦合違背面向接口編程。
  3. 字段注入容易 NPE。
  4. 自動(dòng)裝配有坑。
  5. 單元測(cè)試不好寫(xiě)。

那到底咋辦?用 構(gòu)造函數(shù)注入,清晰、穩(wěn)健、測(cè)試友好,官方推薦不是沒(méi)道理的。

但話(huà)說(shuō)回來(lái),@Autowired 也不是不能用,只是你得分場(chǎng)景。

責(zé)任編輯:武曉燕 來(lái)源: 蘇三說(shuō)技術(shù)
相關(guān)推薦

2022-09-26 10:26:27

FieldIDEASpring

2023-09-27 23:03:01

Java虛擬線(xiàn)程

2024-11-12 10:30:54

Docker部署數(shù)據(jù)庫(kù)

2024-06-04 00:10:00

開(kāi)發(fā)拷貝

2024-09-12 08:32:42

2021-08-23 13:02:50

MySQLJOIN數(shù)據(jù)庫(kù)

2023-11-06 13:04:59

Python日志庫(kù)

2022-01-11 10:29:32

Docker文件掛載

2025-04-29 07:06:20

2021-01-13 09:55:29

try-catch-fJava代碼

2018-11-29 14:30:42

數(shù)據(jù)庫(kù)外鍵約束應(yīng)用程序

2021-07-04 14:19:03

RabbitMQ消息轉(zhuǎn)換

2020-08-31 11:20:53

MySQLuuidid

2024-03-11 11:02:03

Date類(lèi)JavaAPI

2020-10-19 11:05:17

SpringTransaction事務(wù)

2020-07-02 14:12:52

C++語(yǔ)言編程

2024-07-29 09:03:00

2023-09-07 17:06:21

@Autowired報(bào)錯(cuò)原因分析

2025-02-24 10:36:15

2021-09-08 07:58:58

字節(jié)系統(tǒng)雙寫(xiě)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)