Spring為什麼不推薦使用@Autowired註解詳析

引言

使用IDEA開發時,同組小夥伴都喜歡用@Autowired註入,代碼一片warning,看著很不舒服,@Autowired作為Spring的親兒子,為啥在IDEA中提示瞭一個警告:Field injection is not recommended

想搞清楚這個問題之前,首先先瞭解一下依賴註入的幾種方式

Spring的三種註入方式

屬性(filed)註入

這種註入方式就是在bean的變量上使用註解進行依賴註入。本質上是通過反射的方式直接註入到field。這是我平常開發中看的最多也是最熟悉的一種方式。

@Autowired 
UserDao userDao;

構造器註入

將各個必需的依賴全部放在帶有註解構造方法的參數中,並在構造方法中完成對應變量的初始化,這種方式,就是基於構造方法的註入。比如:

final
UserDao userDao;

@Autowired
public UserServiceImpl(UserDao userDao) {
    this.userDao = userDao;
}

set方法註入

通過對應變量的setXXX()方法以及在方法上面使用註解,來完成依賴註入。比如:

private UserDao userDao;

@Autowired
public void setUserDao (UserDao userDao) {
    this.userDao = userDao;
}

屬性註入可能出現的問題

問題一

基於 field 的註入可能會帶來一些隱含的問題。來我們舉個例子:

@Autowired
private User user;

private String company;

public UserDaoImpl(){
    this.company = user.getCompany();
}

編譯過程不會報錯,但是運行之後報NullPointerException

Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate […]: Constructor threw exception; nested exception is java.lang.NullPointerException

Java 在初始化一個類時,是按照靜態變量或靜態語句塊 –> 實例變量或初始化語句塊 –> 構造方法 -> @Autowired 的順序。所以在執行這個類的構造方法時,user對象尚未被註入,它的值還是 null。

問題二

不能有效的指明依賴。相信很多人都遇見過一個bug,依賴註入的對象為null,在啟動依賴容器時遇到這個問題都是配置的依賴註入少瞭一個註解什麼的。這種方式就過於依賴註入容器瞭,當沒有啟動整個依賴容器時,這個類就不能運轉,在反射時無法提供這個類需要的依賴。

問題三

依賴註入的核心思想之一就是被容器管理的類不應該依賴被容器管理的依賴,換成白話來說就是如果這個類使用瞭依賴註入的類,那麼這個類擺脫瞭這幾個依賴必須也能正常運行。然而使用變量註入的方式是不能保證這點的。

spring建議

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.

翻譯過來就是:

強制依賴就用構造器方式
可選、可變的依賴就用setter註入

使用@Resource代替@Autowired

@Resource有2個屬性name和type。在spring中name屬性定義為bean的名字,type這是bean的類型。如果屬性上加@Resource註解那麼他的註入流程是

  • 如果同時指定瞭name和type,則從Spring上下文中找到唯一匹配的bean進行裝配,找不到則拋出異常。
  • 如果指定瞭name,則從上下文中查找名稱匹配的bean進行裝配,找不到則拋出異常。
  • 如果指定瞭type,則從上下文中找到類型匹配的唯一bean進行裝配,找不到或是找到多個,都會拋出異常。
  • 如果既沒有指定name,又沒有指定type,則默認按照byName方式進行裝配;如果沒有匹配,按照byType進行裝配。

@Autowired隻根據type進行註入,不會去匹配name。如果涉及到type無法辨別註入對象時,那需要依賴@Qualifier或@Primary註解一起來修飾。

使用@RequiredArgsConstructor構造器方式註入

這種形式就是Spring推薦使用的構造器方式註入,此種方式是lombok包下的註解,如果使用此種方式,需要項目中引入lombok,例如:

@RequiredArgsConstructor
public class UserDaoImpl{
	private final User user;
}

總結

到此這篇關於Spring為什麼不推薦使用@Autowired註解的文章就介紹到這瞭,更多相關Spring使用@Autowired註解內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: