Spring 2.5 引入基於註解的配置方式 (@Service、@Autowired、@Qualifier),大幅簡化 XML 配置。本文透過完整範例示範:元件掃描、Bean 定義、依賴注入、多實現類限定、單元測試驗證。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="
https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-2.5.xsd
https://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!-- 1. 啟用註解驅動 -->
<context:annotation-config/>
<!-- 2. 元件掃描基礎套件 -->
<context:component-scan base-package="org.example"/>
</beans>
context:annotation-config:啟用 @Autowired、@Resource、@PostConstruct、@PreDestroy 等註解處理器context:component-scan:掃描 org.example 及子套件下的 @Component、@Service、@Repository、@Controller 類別,自動註冊為 Bean
org.example
├── IMan.java # 介面
├── ChineseMan.java # 實作 1 (@Service)
├── EnglishMan.java # 實作 2 (@Service("usMan"))
├── SimpleMan.java # 使用者 (@Service + @Autowired)
└── SpringTest.java # 測試類
package org.example;
public interface IMan {
String sayHello();
}
package org.example;
import org.springframework.stereotype.Service;
@Service
public class ChineseMan implements IMan {
public String sayHello() { return "抽你丫的"; }
}
package org.example;
import org.springframework.stereotype.Service;
@Service("usMan") // 指定 Bean ID 為 "usMan"
public class EnglishMan implements IMan {
public String sayHello() { return this + " said: Fuck you!"; }
}
package org.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class SimpleMan {
// 1. 自動注入名為 "chineseMan" 的 Bean
@Autowired(required = false)
@Qualifier("chineseMan") // 限定具體 Bean
private IMan man;
public IMan getMan() { return man; }
public void setMan(IMan man) { this.man = man; }
public String hello() {
System.out.println("man.sayHello()=" + man.sayHello());
return "SimpleMan said: Hi";
}
}
| 註解 | 作用 | 關鍵屬性 |
|---|---|---|
@Service | 定義 Service 層 Bean,屬 @Component 特化 | value: Bean ID (預設類名首字母小寫) |
@Autowired | 自動裝配 (byType),可用於建構子、Setter、欄位 | required=false: 允許找不到 Bean 時不報錯 |
@Qualifier | 限定 Bean 名稱 (byName),配合 @Autowired 使用 | value: Bean ID |
| 方式 | 程式碼 | 優點 |
|---|---|---|
| 欄位注入 | @Autowired @Qualifier("x") private IMan man; | 簡潔、不可變 (final 配合建構子) |
| Setter 注入 | @Autowired public void setMan(@Qualifier("x") IMan man) | 可選依賴、易測試 (手動注入 Mock) |
| 建構子注入 | @Autowired public SimpleMan(@Qualifier("x") IMan man) | 不可變、強制依賴、循環依賴檢測 |
推薦:Spring 4.3+ 單一建構子可省略 @Autowired,建構子注入為首選。
| 特性 | @Autowired (Spring) | @Resource (JSR-250) |
|---|---|---|
| 匹配策略 | 優先 byType,再 byName | 優先 byName,再 byType |
| 指定名稱 | @Qualifier("name") | @Resource(name="name") |
| 標準化 | Spring 專有 | Java EE 標準 |
若需定義 java.lang.String 類型的 Bean 並注入:
<bean id="myString" class="java.lang.String">
<constructor-arg value="hello world"/>
</bean>
@Autowired @Qualifier("myString") private String myStr; // 注入成功
或使用 @Value("${property.key}") 注入屬性檔值 (需 PropertyPlaceholderConfigurer)。
beans.xml 僅保留 component-scan、資料源、交易管理等基礎設施