為什么禁止在SpringBoot項目中使用@Autowired注解
Spring 官方已不推薦使用 Autowired 字段/屬性注入 bean,一些大公司的新項目也明令禁止使用了。
說明
最近公司升級框架,由原來的 spring framework 3.0 升級到 5.0,然后寫代碼的時候突然發(fā)現(xiàn) idea 在屬性注入的 @Autowired 注解上給出警告提示,就像下面這樣的,也是挺懵逼的,畢竟這么寫也很多年了。
Field injection is not recommended?
查閱了相關(guān)文檔了解了一下,原來這個提示是 spring framework 4.0 以后開始出現(xiàn)的,spring 4.0 開始就不推薦使用屬性注入,改為推薦構(gòu)造器注入和 setter 注入。
下面將展示了 spring 框架可以使用的不同類型的依賴注入,以及每種依賴注入的適用情況。
依賴注入的類型
盡管針對 spring framework 5.1.3 的文檔只定義了兩種主要的依賴注入類型,但實際上有三種:
- 基于構(gòu)造器的依賴注入
- 基于 setter 的依賴注入
- 基于字段的依賴注入
其中基于字段的依賴注入被廣泛使用,但是 idea 或者其他靜態(tài)代碼分析工具會給出提示信息,不推薦使用。
甚至可以在一些 Spring 官方指南中看到這種注入方法:
2.1 基于構(gòu)造器的依賴注入
在基于構(gòu)造函數(shù)的依賴注入中,類構(gòu)造函數(shù)被標注為 @Autowired,并包含了許多與要注入的對象相關(guān)的參數(shù)。
@Component public class ConstructorBasedInjection { private final InjectedBean injectedBean; @Autowired public ConstructorBasedInjection(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
然后在spring官方文檔中,@Autowired 注解也是可以省去的。
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on a MovieFinder private MovieFinder movieFinder; // a constructor so that the Spring container can inject a MovieFinder public SimpleMovieLister(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually uses the injected MovieFinder is omitted... }
基于構(gòu)造函數(shù)注入的主要優(yōu)點是可以將需要注入的字段聲明為 final, 使得它們會在類實例化期間被初始化,這對于所需的依賴項很方便。
2.2 基于 Setter 的依賴注入
在基于 setter 的依賴注入中,setter 方法被標注為 @Autowired。一旦使用無參數(shù)構(gòu)造函數(shù)或無參數(shù)靜態(tài)工廠方法實例化 Bean,為了注入 Bean 的依賴項,Spring 容器將調(diào)用這些 setter 方法。
@Component public class SetterBasedInjection { private InjectedBean injectedBean; @Autowired public void setInjectedBean(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
和基于構(gòu)造器的依賴注入一樣,在官方文檔中,基于 Setter 的依賴注入中的 @Autowired 也可以省去。
public class SimpleMovieLister { // the SimpleMovieLister has a dependency on the MovieFinder private MovieFinder movieFinder; // a setter method so that the Spring container can inject a MovieFinder public void setMovieFinder(MovieFinder movieFinder) { this.movieFinder = movieFinder; } // business logic that actually uses the injected MovieFinder is omitted... }
2.3 基于屬性的依賴注入
在基于屬性的依賴注入中,字段/屬性被標注為 @Autowired。一旦類被實例化,Spring 容器將設(shè)置這些字段。
@Component public class FieldBasedInjection { @Autowired private InjectedBean injectedBean; }
正如所看到的,這是依賴注入最干凈的方法,因為它避免了添加樣板代碼,并且不需要聲明類的構(gòu)造函數(shù)。代碼看起來很干凈簡潔,但是正如代碼檢查器已經(jīng)向我們暗示的那樣,這種方法有一些缺點。
基于字段的依賴注入缺陷
3.1 不允許聲明不可變域
基于字段的依賴注入在聲明為 final/immutable 的字段上不起作用,因為這些字段必須在類實例化時實例化。聲明不可變依賴項的唯一方法是使用基于構(gòu)造器的依賴注入。
3.2 容易違反單一職責(zé)設(shè)計原則
在面向?qū)ο蟮木幊讨?,五大設(shè)計原則SOLID被廣泛應(yīng)用,(國內(nèi)一般為六大設(shè)計原則),用以提高代碼的重用性,可讀性,可靠性和可維護性。
S 在 SOLID 中代表單一職責(zé)原則,即一個類應(yīng)該只負責(zé)一項職責(zé),這個類提供的所有服務(wù)都應(yīng)該只為它負責(zé)的職責(zé)服務(wù)。
使用基于字段的依賴注入,高頻使用的類隨著時間的推移,我們會在類中逐漸添加越來越多的依賴項,我們用著很爽,很容易忽略類中的依賴已經(jīng)太多了。但是如果使用基于構(gòu)造函數(shù)的依賴注入,隨著越來越多的依賴項被添加到類中,構(gòu)造函數(shù)會變得越來越大,我們一眼就可以察覺到哪里不對勁。
有一個有超過10個參數(shù)的構(gòu)造函數(shù)是一個明顯的信號,表明類已經(jīng)轉(zhuǎn)變一個大而全的功能合集,需要將類分割成更小、更容易維護的塊。
因此,盡管屬性注入并不是破壞單一責(zé)任原則的直接原因,但它隱藏了信號,使我們很容易忽略這些信號。
3.3 與依賴注入容器緊密耦合
使用基于字段的依賴注入的主要原因是為了避免 getter 和 setter 的樣板代碼或為類創(chuàng)建構(gòu)造函數(shù)。最后,這意味著設(shè)置這些字段的唯一方法是通過Spring容器實例化類并使用反射注入它們,否則字段將保持 null。
依賴注入設(shè)計模式將類依賴項的創(chuàng)建與類本身分離開來,并將此責(zé)任轉(zhuǎn)移到類注入容器,從而允許程序設(shè)計解耦,并遵循單一職責(zé)和依賴項倒置原則(同樣可靠)。因此,通過自動裝配(autowiring)字段來實現(xiàn)的類的解耦,最終會因為再次與類注入容器(在本例中是 Spring)耦合而丟失,從而使類在Spring容器之外變得無用。
這意味著,如果您想在應(yīng)用程序容器之外使用您的類,例如用于單元測試,您將被迫使用 Spring 容器來實例化您的類,因為沒有其他可能的方法(除了反射)來設(shè)置自動裝配字段。
3.4 隱藏依賴關(guān)系
在使用依賴注入時,受影響的類應(yīng)該使用公共接口清楚地公開這些依賴項,方法是在構(gòu)造函數(shù)中公開所需的依賴項,或者使用方法(setter)公開可選的依賴項。當使用基于字段的依賴注入時,實質(zhì)上是將這些依賴對外隱藏了。
總結(jié)
我們已經(jīng)看到,基于字段的注入應(yīng)該盡可能地避免,因為它有許多缺點,無論它看起來多么優(yōu)雅。推薦的方法是使用基于構(gòu)造函數(shù)和基于setter的依賴注入。對于必需的依賴,建議使用基于構(gòu)造函數(shù)的注入,設(shè)置它們?yōu)椴豢勺兊?,并防止它們?yōu)?null。對于可選的依賴項,建議使用基于 setter 的注入。
到此這篇關(guān)于為什么禁止在SpringBoot項目中使用@Autowired注解的文章就介紹到這了,更多相關(guān)禁止SpringBoot中使用@Autowired注解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java語言實現(xiàn)簡單FTP軟件 FTP連接管理模塊實現(xiàn)(8)
這篇文章主要為大家詳細介紹了Java語言實現(xiàn)簡單FTP軟件,F(xiàn)TP連接管理模塊的實現(xiàn)方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04SpringCloud項目的log4j2漏洞解決方案詳解流程
很多小伙伴因為Log4j2的驚爆0Day漏洞一時束手無策,這里提供最終解決方案可以進行一個版本號的升級,感興趣的朋友來看看吧2022-04-04java并發(fā)編程專題(十一)----(JUC原子類)數(shù)組類型詳解
這篇文章主要介紹了JAVA JUC原子類 數(shù)組類型詳解的相關(guān)資料,文中示例代碼非常詳細,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-07-07Java數(shù)組常見應(yīng)用詳解【創(chuàng)建、遍歷、排序、查找】
這篇文章主要介紹了Java數(shù)組常見應(yīng)用,結(jié)合實例形式詳細分析了java數(shù)組的基本定義、創(chuàng)建、遍歷、排序、查找等相關(guān)操作技巧與使用注意事項,需要的朋友可以參考下2020-02-02Java中將MultipartFile和File互轉(zhuǎn)的方法詳解
我們在開發(fā)過程中經(jīng)常需要接收前端傳來的文件,通常需要處理MultipartFile格式的文件,今天來介紹一下MultipartFile和File怎么進行優(yōu)雅的互轉(zhuǎn),需要的朋友可以參考下2023-10-10