Spring 2.5+ 引入註解驅動,旨在減少 XML 配置、提升開發效率。核心在於**依賴注入 (DI) 註解**與**組件掃描機制**的結合。
| 註解 | 來源 | 預設策略 | 關鍵屬性 | 適用場景 |
|---|---|---|---|---|
@Autowired | Spring | **byType** (類型) | required (預設 true) | 單一候選者、建構子/Setter/欄位注入 |
@Resource | JSR-250 | **byName** (名稱) | name、type | 需指定 Bean 名稱、多實現選擇 |
@Qualifier | Spring | 輔助 @Autowired 指定名稱 | value (beanName) | @Autowired 多候選時消歧義 |
name="" 且 byName 失敗 → 退回 byTypename="xxx" → **僅** byName,失敗拋異常@Autowired
@Qualifier("student") // 指定 bean name
private Student student;
// 或建構子注入 (推薦,不可變、易測試)
@Autowired
public Person(@Qualifier("student") Student student) {
this.student = student;
}
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:context="https://www.springframework.org/schema/context"
xsi:schemaLocation="...
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 僅需這一行啟用 @Autowired/@Resource/@PostConstruct 等 -->
<context:annotation-config/>
</beans>
<context:component-scan base-package="com.example.service"/>
掃描指定包及子包,自動註冊帶有下列註解的類為 Bean:
| 註解 | 語義層級 | 等價 XML |
|---|---|---|
@Component | 通用組件 | <bean id="className" class="..."/> |
@Repository | DAO/持久層 | + 異常轉換 AOP |
@Service | 業務邏輯層 | 語義標記 |
@Controller | Web 控制層 | 語義標記、Spring MVC 掃描 |
Bean 名稱預設:類名首字母小寫 (如 UserServiceImpl → userServiceImpl);可指定 @Component("myBean") 自訂。
public interface Document { void read(); void write(); }
@Component("excelDocument")
public class ExcelDocument implements Document { /* ... */ }
@Component("pdfDocument")
public class PDFDocument implements Document { /* ... */ }
@Component("wordDocument")
public class WordDocument implements Document { /* ... */ }
@Component("documentManager")
public class DocumentManager {
@Resource(name = "excelDocument") // 指定實作
private Document document;
public void read() { document.read(); }
public void write() { document.write(); }
}
<context:component-scan base-package="com.example.document"/>
@Repository("personDao")
public class PersonDaoImpl implements PersonDao { /* ... */ }
@Service("personService")
public class PersonServiceImpl implements PersonService {
@Resource(name = "personDao")
private PersonDao personDao;
// ...
}
@Controller("personAction")
public class PersonAction {
@Resource(name = "personService")
private PersonService personService;
// ...
}
注意:基於註解配置**無需**父 Bean 機制,Java 繼承/組合更自然。此處僅作舊專案維護參考。
<bean id="baseBean" class="com.example.TestBean" abstract="true">
<property name="sex" value="male"/>
</bean>
<bean id="bean1" parent="baseBean"/> <!-- 繼承屬性 -->
<bean id="bean3" parent="baseBean"> <!-- 覆蓋屬性 -->
<property name="sex" value="female"/>
</bean>
<bean id="baseSex" abstract="true">
<property name="sex" value="male"/>
</bean>
<bean id="bean1" class="..." parent="baseSex"> ... </bean>
<bean id="bean2" class="..." parent="baseSex"/>
多個不同類別 Bean 共享相同屬性值,減少 TransactionProxyFactoryBean 等舊式 AOP 配置冗餘。
| 維度 | 註解驅動 | XML 配置 |
|---|---|---|
| 開發效率 | 高 (碼即配置) | 低 (切換檔案) |
| 集中管理 | 分散在類上 | 集中在 XML、易全景檢視 |
| 環境差異 | 較難 (需 Profile/條件註解) | 易 (多套 XML) |
| 第三方庫整合 | 無法修改源碼加註解 | 唯一選項 |
| 建議 | **專案主流**:自有代碼用註解 | **補充**:第三方 Bean、環境差異、基礎設施 |