基于@Autowired依賴注入的原理分析
@Autowired 是 Spring 框架中的一個注解,用于自動注入依賴。
在 Spring 中,依賴注入(Dependency Injection, DI)是一種設計模式,允許在運行時將對象的依賴關系(即所需的其他對象)自動提供給它,而不是在代碼中手動創(chuàng)建依賴對象。
1、介紹
以下為注解的結構圖

該注解支持標注在字段、構造函數、方法以及參數上。
注意:
其中的關鍵屬性 required 默認值為 true,表示如果沒有合適的 Bean 可以注入,則會拋出異常。required 如果為false的時候,表示可以暫時不實例化。
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}2、實現原理
1、掃描及注冊 Bean
Spring 在啟動時會掃描配置的包,找到被@Compoent、@Service、@Repository和@Controller等注解標記的類,并將它們注冊為 Spring 容器中的 Beans。
2、解析依賴
當 Spring 創(chuàng)建一個 Bean 時,它會檢查該 Bean 的構造函數、方法或字段中是否有@Autowired注解。
這個注解表明該字段、構造函數或方法是需要進行依賴注入的。
3、類型匹配
Spring 會根據變量的類型去容器中查找匹配的 Bean,默認情況下,Spring 使用的是按類型自動裝配。
- 如果找到唯一的匹配項,就會將其注入。
- 如果有多個匹配項,Spring 會拋出異常;可以通過設置required
=false或者使用 @Qualifier或者@Primary來解決歧義問題。 - 如果沒有匹配項,通常會返回 null(前提是字段是可空的)。
3、使用場景
3.1、背景
當 Spring 容器檢測到有多個同類型的 Bean 可供注入時,默認的行為是拋出 NoUniqueBeanDefinitionException 異常。
3.2、處理方式
1、@Qualifier
如果有多個相同類型的 Bean 時,可以使用 @Qualifier 注解來明確指定要注入的 Bean。
代碼示例:
@Autowired
@Qualifier("specificBeanName")
private MyService myService;2、@Primary注解

1、目的
主要目的是在 Spring 容器中有多個相同類型的 Bean 存在時,提供一種機制來指定哪個 Bean 應該被優(yōu)先考慮作為默認注入的目標。
2、原理
如果其中一個 Bean 被標記為 @Primary,那么 Spring 將會選擇它作為首選項并完成注入過程。
此邏輯發(fā)生在 Spring 的自動裝配階段,在這一階段,容器會評估所有可用的候選 Bean,并根據各種規(guī)則(如 @Primary、@Qualifier 等)做出最終決策。
3、示例
@Configuration
public class AppConfig {
@Bean
@Primary
public MyService primaryMyService() {
return new MyServiceImpl1();
}
@Bean
public MyService secondaryMyService() {
return new MyServiceImpl2();
}
}在這個配置文件中,我們有兩個實現了 MyService接口的服務類——MyServiceImpl1 和 MyServiceImpl2。由于我們在第一個服務實現上加了 @Primary 注解,因此無論何時需要注入 MyService類型的對象,都會優(yōu)先選取 MyServiceImpl1 實例。
3.3、替代方式
1. @Inject
@Inject 是 Java EE 提供的標準注解,也可以在 Spring 中使用。
它的功能類似于@Autowired,但語義更加清晰,因為它僅關注依賴注入本身而不涉及 Spring 特定的功能。
public class ExampleService {
private final AnotherService anotherService;
@Inject
public ExampleService(AnotherService anotherService) {
this.anotherService = anotherService;
}
}2. 構造函數注入
這種方式被認為是最佳實踐之一,尤其適用于強制性依賴項。相比于字段注入或 setter 方法注入,構造函數注入能更好地滿足不可變性和測試需求。
示例:
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) { // 構造函數注入
this.userRepository = userRepository;
}
}3. @Resource
@Resource 是 JNDI 規(guī)范的一部分,通?;诿Q匹配來查找目標 Bean。
如果沒有找到與名字完全一致的 Bean,則會退回到按類型匹配的方式。相比 @Autowired 更加靈活,因為可以直接指定要注入的具體資源名。
示例:
public class MovieRecommender {
@Resource(name="mainDataSource") // 明確指定了數據源的名字
DataSource dataSource;
public void recommend() {}
}4、總結
通俗講解
把@Autowired看成是一種“智能化的手”。當你需要一個助手(依賴對象)來完成某個任務時,你不需要去親自找尋和雇傭這個助手,Spring 就像一個高效的秘書,知道你需要什么助手,會自動給你安排好。
你只需要告訴 Spring 你需要的助手的類型,它就會負責尋找并提供給你,而不需要你關心具體的細節(jié)。
這樣做的好處是可以降低代碼的耦合度,讓程序的各個部分更容易進行單元測試和維護。只要我們在代碼中聲明需要的依賴,Spring 就會負責去處理這些依賴,讓開發(fā)者能更專注于業(yè)務邏輯的實現。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Spring框架原理之實例化bean和@Autowired實現原理方式
這篇文章主要介紹了Spring框架原理之實例化bean和@Autowired實現原理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-05-05
Java Swing實現JTable檢測單元格數據變更事件的方法示例
這篇文章主要介紹了Java Swing實現JTable檢測單元格數據變更事件的方法,結合完整實例形式分析了Swing實現JTable檢測單元格數據變更事件過程中出現的問題與相關解決方法,需要的朋友可以參考下2017-11-11

