在使用IDEA進行開發時,在字段上使用Spring的依賴注入注解@Autowired
后會出現如下警告
Field injection is not recommended (字段注入是不被推薦的)?
?這個原因具體可以看看:
【注解使用】使用@Autowired后提示:Field injection is not recommended(Spring團隊不推薦使用Field注入)
?【Spring】淺談spring為什么推薦使用構造器注入
我們這里討論:
使用@Resource
卻不會出現此提示
網上文章大部分都是介紹兩者的區別,沒有提到為什么
Spring常見的DI方式
-
構造器注入?:利用構造方法的參數注入依賴
-
Setter注入?:調用Setter的方法注入依賴
-
字段注入?:在字段上使用
@Autowired/Resource
注解
@Resource注解也可以完成屬性注入。那它和@Autowired注解有什么區別?
-
@Resource注解是JDK擴展包中的,也就是說屬于JDK的一部分。所以該注解是標準注解,更加具有通用性。(JSR-250標準中制定的注解類型。JSR是Java規范提案。)
-
@Autowired注解是Spring框架自己的。
-
@Resource注解默認根據名稱裝配byName,未指定name時,使用屬性名作為name。通過name找不到的話會自動啟動通過類型byType裝配。
-
@Autowired注解默認根據類型裝配byType,如果想根據名稱裝配,需要配合@Qualifier注解一起用。
-
@Resource注解用在屬性上、setter方法上。
-
@Autowired注解用在屬性上、setter方法上、構造方法上、構造方法參數上。
各種DI方式的優缺點
參考Spring官方文檔,建議了如下的使用場景:
-
構造器注入?:強依賴性?(即必須使用此依賴),不變性?(各依賴不會經常變動)
-
Setter注入?:可選?(沒有此依賴也可以工作),可變?(依賴會經常變動)
-
Field注入?:大多數情況下盡量少使用?字段注入,一定要使用的話,?@Resource相對@Autowired?對IoC容器的耦合更低
?
Field注入的缺點
-
不能像構造器那樣注入不可變的對象
-
依賴對外部不可見?,外界可以看到構造器和setter,但無法看到私有字段,自然無法了解所需依賴
-
會導致組件與IoC容器緊耦合?(這是最重要的原因,離開了IoC容器去使用組件,在注入依賴時就會十分困難)
-
導致單元測試也必須使用IoC容器?,原因同上
-
依賴過多時不夠明顯?,比如我需要10個依賴,用構造器注入就會顯得龐大,這時候應該考慮一下此組件是不是違反了單一職責原則
為什么IDEA只對@Autowired警告
Field注入雖然有很多缺點,但它的好處也不可忽略:那就是太方便了?。使用構造器或者setter注入需要寫更多業務無關的代碼,十分麻煩,而字段注入大幅簡化了它們。并且絕大多數情況下業務代碼和框架就是強綁定的,完全松耦合只是一件理想上的事,犧牲了敏捷度去過度追求松耦合反而得不償失。
那么問題來了,為什么IDEA只對@Autowired警告,卻對@Resource視而不見呢?
1、@Autowired?是Spring?提供的,它是特定IoC提供的特定注解?,這就導致了應用與框架的強綁定?,一旦換用了其他的IoC框架,是不能夠支持注入?的。
而?@Resource?是JSR-250?提供的,它是Java標準?,我們使用的IoC容器應當去兼容它,這樣即使更換容器,也可以正常工作。
2、@Autowired和 @Resource的默認注入方式不同,@Autowired默認是根據類型進行注入的, @Resource默認是先根據名字注入,找不到再根據類型注入的。所以,相比于 @Autowired 注解,@Resource 注解更加靈活,但同時也更難以確保依賴項的正確性。如果無法確定自動注入的 Bean 是否正確,可以通過 @Qualifier 注解或者手動注入的方式顯式指定 Bean 的名稱或類型,避免依賴項注入的錯誤和困擾。
參考文章:
為什么在Spring中使用@Autowired時會報錯 而@Resource不會
為什么 Spring和IDEA 都不推薦使用 @Autowired 注解
?