<span style="outline: 0px;font-size: 16px;visibility: visible;">spring framerwork 3.0</span>
升級到<span style="outline: 0px;font-size: 16px;visibility: visible;">#5.0</span>
##,然後寫程式碼的時候突然發現idea在屬性注入的 @Autowired 註解上給出警告提示,就像下面這樣的,也挺懵逼的,畢竟這麼寫也很多年了。
Field injection is not recommended
查閱了相關文件了解了一下,原來這個提示是<span style="outline: 0px;font-size: 16px;visibility: visible;">spring framerwork 4.0</span>
以後開始出現的,spring 4.0開始就不推薦使用屬性注入,改為推薦構造器注入和setter注入。
下面將展示了spring框架可以使用的不同類型的依賴注入,以及每種依賴注入的適用情況。
2、依賴注入的類型
##儘管針對 spring framerwork 5.1.3<span style="outline: 0px;font-size: 16px;"></span>
的文件只定義了兩個主要的依賴注入類型,但實際上有三種;#
#其中<span style="outline: 0px;font-size: 16px;">基於字段的依賴注入</span>
#被廣泛使用,但是idea或其他靜態程式碼分析工具會給予提示訊息,不建議使用。 ############甚至可以在一些Spring官方指南中看到這種注入方法:####################### #2.1 基於建構子的依賴注入###############在基於建構子的依賴注入中,類別建構子被標註為@Autowired,並包含了許多與要注入的對象相關的參數。 ######
@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... }
基于构造函数注入的主要优点是可以将需要注入的字段声明为final, 使得它们会在类实例化期间被初始化,这对于所需的依赖项很方便。
在基于setter的依赖注入中,setter方法被标注为 @Autowired。一旦使用无参数构造函数或无参数静态工厂方法实例化Bean,为了注入Bean的依赖项,Spring容器将调用这些setter方法。
@Component public class SetterBasedInjection { private InjectedBean injectedBean; @Autowired public void setInjectedBean(InjectedBean injectedBean) { this.injectedBean = injectedBean; } }
和基于构造器的依赖注入一样,在官方文档中,基于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... }
在基于属性的依赖注入中,字段/属性被标注为 @Autowired。一旦类被实例化,Spring容器将设置这些字段。
@Component public class FieldBasedInjection { @Autowired private InjectedBean injectedBean; }
正如所看到的,这是依赖注入最干净的方法,因为它避免了添加样板代码,并且不需要声明类的构造函数。代码看起来很干净简洁,但是正如代码检查器已经向我们暗示的那样,这种方法有一些缺点。
3、基於欄位的依賴注入缺陷
基於欄位的依賴注入在宣告為final/immutable的欄位上不起作用,因為這些欄位必須在類別實例化時實例化。聲明不可變依賴項的惟一方法是使用基於建構器的依賴注入。
在物件導向的程式設計中,五大設計原則SOLID被廣泛應用,(國內一般為六大設計原則),用以提高程式碼的重用性,可讀性,可靠性和可維護性
##S在SOLID中代表單一職責原則,即一個類別應該只負責一項職責,這個類別提供的所有服務都應該只為它負責的職責服務。
使用基於字段的依賴注入,高頻使用的類別隨著時間的推移,我們會在類別中逐漸添加越來越多的依賴項,我們用著很爽,很容易忽略類別中的依賴已經太多了。但是如果使用基於建構函數的依賴注入,隨著越來越多的依賴項被添加到類別中,構造函數會變得越來越大,我們一眼就可以察覺到哪裡不對勁。
有一個有超過10個參數的建構函數是一個明顯的訊號,表示類別已經轉變一個大而全的函數集合,需要將類別分割成更小、更容易維護的塊。
因此,儘管屬性注入並不是破壞單一責任原則的直接原因,但它隱藏了訊號,使我們很容易忽略這些訊號。
#使用基於欄位的依賴注入的主要原因是為了避免getter和setter的樣板程式碼或為類別建立建構函式。最後,這意味著設定這些欄位的唯一方法是透過Spring容器實例化類別並使用反射注入它們,否則欄位將保持null。
依賴注入設計模式將類別依賴項的建立與類別本身分開來,並將此責任轉移到類別注入容器,從而允許程式設計解耦,並遵循單一職責和依賴項倒置原則(同樣可靠)。因此,透過自動組裝(autowiring)欄位來實現的類別的解耦,最終會因為再次與類別注入容器(在本例中是Spring)耦合而丟失,從而使類別在Spring容器之外變得無用。
這意味著,如果您想在應用程式容器之外使用您的類,例如用於單元測試,您將被迫使用Spring容器來實例化您的類,因為沒有其他可能的方法(除了反射)來設定自動裝配欄位。
#在使用依賴注入時,受影響的類別應該使用公共介面清楚地公開這些依賴項,方法是在建構函數中公開所需的依賴項,或使用方法(setter)公開可選的依賴項。當使用基於字段的依賴注入時,實質上是將這些依賴對外隱藏了。
4、總結
我們已經看到,基於字段的注入應該盡可能地避免,因為它有許多缺點,無論它看起來多麼優雅。建議的方法是使用基於建構函式和基於setter的依賴注入。
對於必要的依賴,建議使用基於建構函式的注入,設定它們為不可變的,並防止它們為null。對於可選的依賴項,建議使用基於setter的注入。
以上是大公司為什麼禁止在 Spring Boot 專案中使用 @Autowired 註解?的詳細內容。更多資訊請關注PHP中文網其他相關文章!