天天看點

Intellij IDEA 如何去掉 @Autowired 注入警告

問題

在Service層注入Mybatis的Mapper我們通常會使用

@Autowired

自動注入

@Autowired
private ProductMapper productMapper;      

但是這樣Intellij IDEA會顯示紅色告警,提示不能自動注入。

Intellij IDEA 如何去掉 @Autowired 注入警告

當我們在Controller層注入Service時我們也經常直接在Filed上使用

@Autowired

注解,這時候不顯示紅色警告,但是也顯示

Field injection is not recommended

的建議

Intellij IDEA 如何去掉 @Autowired 注入警告

原因

第一種情況是因為IDEA可以識别并了解Spring的上下文。然而Mapper接口是Mybatis的,IDEA了解不了。是以會出現紅色告警。

而第二種原因是因為官方不推薦使用Filed進行注解,而推薦使用構造器或Setter方法進行注解,像下面兩種寫法就不會出現警告。

private final ProductService productService;
@Autowired
public ProductController(ProductService productService) {
    this.productService = productService;
}      

or

private ProductService productService;
@Autowired
public void setProductService(ProductService productService) {
    this.productService = productService;
}      

問題是什麼

Field注入看起來非常好,夠簡潔,代碼通俗易懂。你的類可以專注于業務而不被依賴注入所污染。你隻需要把@Autowired扔到變量之上就好了,不需要特殊的構造器或者set方法,依賴注入容器會提供你所需的依賴。但是Field注入會帶來2個問題:

  • 當注入的對象依賴其他對象,而被依賴的對象沒被建立的話就會出現空指針異常。
  • 這樣的類沒辦法在容器之外被重用,也不能期望反射提供其所需的依賴。

詳細原因大家可以去這篇文章檢視:

http://olivergierke.de/2013/11/why-field-injection-is-evil/

構造器注入 VS Setter注入

Setter應該被用來注入可變的依賴。當沒有提供依賴時,這個類也應該能夠運轉。當執行個體化對象後,這些依賴也能随時改變。其實也視情況而變,有時,一個不變的對象是理想狀态。有時,最好是能在運作期間改變對象的屬性。

構造器注入對象需要依賴的對象初始化後才能正常運轉,通過構造器提供這些依賴就能保證對象初始化後就能被使用。使用構造器注入的一個可能的影響就是循環依賴。

怎麼解決

我們可以使用Lombok提供的注解

@RequiredArgsConstructor

來解決這兩個問題(Lombok這個大家項目都會使用吧)

@Service
@Log4j2
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ProductServiceImpl implements ProductService {
    private final ProductMapper productMapper;
    ...
}      

這裡必須使用final修飾符來修飾注入的Service或Mapper首先我們看看編譯後的類是什麼樣

Intellij IDEA 如何去掉 @Autowired 注入警告

編譯完成後變成了使用構造器進行注入