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

該注解支持標(biāo)注在字段、構(gòu)造函數(shù)、方法以及參數(shù)上。
注意:
其中的關(guān)鍵屬性 required 默認(rèn)值為 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、實現(xiàn)原理
1、掃描及注冊 Bean
Spring 在啟動時會掃描配置的包,找到被@Compoent、@Service、@Repository和@Controller等注解標(biāo)記的類,并將它們注冊為 Spring 容器中的 Beans。
2、解析依賴
當(dāng) Spring 創(chuàng)建一個 Bean 時,它會檢查該 Bean 的構(gòu)造函數(shù)、方法或字段中是否有@Autowired注解。
這個注解表明該字段、構(gòu)造函數(shù)或方法是需要進(jìn)行依賴注入的。
3、類型匹配
Spring 會根據(jù)變量的類型去容器中查找匹配的 Bean,默認(rèn)情況下,Spring 使用的是按類型自動裝配。
- 如果找到唯一的匹配項,就會將其注入。
- 如果有多個匹配項,Spring 會拋出異常;可以通過設(shè)置required
=false或者使用 @Qualifier或者@Primary來解決歧義問題。 - 如果沒有匹配項,通常會返回 null(前提是字段是可空的)。
3、使用場景
3.1、背景
當(dāng) Spring 容器檢測到有多個同類型的 Bean 可供注入時,默認(rèn)的行為是拋出 NoUniqueBeanDefinitionException 異常。
3.2、處理方式
1、@Qualifier
如果有多個相同類型的 Bean 時,可以使用 @Qualifier 注解來明確指定要注入的 Bean。
代碼示例:
@Autowired
@Qualifier("specificBeanName")
private MyService myService;2、@Primary注解

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

