依賴注入(DI)是 Spring 核心,Bean 裝配是 DI 的具體實現形式。本文系統梳理兩種注入方式、四種自動裝配模式、三大核心註解的使用場景與最佳實踐。
特點:可選依賴、可重新配置、符合 JavaBean 規範
public class Communication {
private Messaging messaging;
// Setter 注入點
public void setMessaging(Messaging messaging) {
this.messaging = messaging;
}
public void communicate() {
messaging.sendMessage();
}
}
XML 配置:
<bean id="activeMqMessaging" class="com.example.ActiveMQMessaging" />
<bean id="communication" class="com.example.Communication">
<property name="messaging">
<ref bean="activeMqMessaging" />
</property>
</bean>
特點:強制依賴、不可變性、循環依賴檢測、單元測試友好
public class Communication {
private final Encryption encryption; // final 確保不可變
// 建構子注入
public Communication(Encryption encryption) {
this.encryption = encryption;
}
public void communicate() {
encryption.encryptData();
}
}
XML 配置:
<bean id="rsaEncryption" class="com.example.RSAEncryption" />
<bean id="communication" class="com.example.Communication">
<constructor-arg type="com.example.Encryption">
<ref bean="rsaEncryption" />
</constructor-arg>
</bean>
顯式指定依賴關係,控制力最強:
<bean id="driver" class="com.example.Driver">
<property name="license" ref="license"/>
</bean>
<bean id="license" class="com.example.License">
<property name="number" value="123456ABCD"/>
</bean>
| 模式 | 匹配規則 | XML 寫法 | 適用場景 |
|---|---|---|---|
| byName | 屬性名 = Bean ID | autowire="byName" | 命名規範嚴格專案 |
| byType | 屬性類型 = Bean 類型 | autowire="byType" | 單一實現類場景 |
| constructor | 建構子參數類型匹配 | autowire="constructor" | 建構子注入專用 |
| no (預設) | 關閉自動裝配,手動指定 | autowire="no" | 精確控制、避免歧義 |
<bean id="application" class="com.example.Application" autowire="byName"/>
<bean id="applicationUser" class="com.example.ApplicationUser">
<property name="name" value="superUser"/>
</bean>
// Application 中有 setApplicationUser(ApplicationUser) 方法
<bean id="employee" class="com.example.Employee" autowire="byType"/>
<bean id="employeeAddress" class="com.example.EmployeeAddress">
<property name="street" value="112/223,SantaVila"/>
</bean>
// Employee 中有 setAddress(EmployeeAddress) 方法
<bean id="performer" class="com.example.Performer" autowire="constructor"/>
<bean id="instrument" class="com.example.Instrument">
<property name="name" value="PIANO"/>
</bean>
// Performer 有建構子 Performer(Instrument)
可用位置:建構子、屬性、Setter 方法、@Configuration 類方法
預設行為:required=true,找不到拋異常
// 屬性注入(最簡潔)
@Component
public class Driver {
@Autowired
private License license;
}
// 建構子注入(推薦,不可變)
@Component
public class Driver {
private final License license;
@Autowired
public Driver(License license) {
this.license = license;
}
}
// Setter 注入
@Component
public class Driver {
private License license;
@Autowired
public void setLicense(License license) {
this.license = license;
}
}
@Component
public class Application {
@Resource(name = "applicationUser")
private ApplicationUser user;
// 若省略 name,預設按屬性名匹配 Bean ID
}
場景:同一介面有多個實現 Bean 時消除歧義
@Component
public class Bond {
@Autowired
@Qualifier("Mustang") // 限定注入名為 Mustang 的 Bean
private Car car;
public void showCar() {
car.getCarName();
}
}
缺少 @Qualifier 異常:
NoUniqueBeanDefinitionException: expected single matching bean but found 2: Ferari, Mustang
// 可選依賴:找不到設為 null 不拋異常
@Autowired(required = false)
private OptionalLicense license;
| 場景 | 推薦註解 | 理由 |
|---|---|---|
| 建構子注入、單一實現 | @Autowired | 類型安全、編譯期檢查、不可變 |
| 多實現需指定具體 Bean | @Autowired + @Qualifier | 精確控制、避免字串硬編碼風險 |
| 需遵循 Java EE 標準 | @Resource | 可移植性、名稱語義清晰 |
| 可選依賴 | @Autowired(required=false) | 優雅降級、避免啟動失敗 |
required=false 防止啟動失敗掌握 DI 核心機制與裝配策略,是構建鬆耦合、高內聚、可測試 Spring 應用的基石。