<property name="dao" ref="dao"/>,靈活、可選依賴。<constructor-arg>,強依賴、不可變對象、循環依賴檢測。IOC 側重控制權轉移的原理;DI 側重依賴賦值的實現過程。兩者描述同一現象的不同視角。
業務邏輯中混雜著事務、日志、安全、緩存等橫切關注點,導致代碼分散、重復、難維護。
<bean id="userService" class="cn.service.UserServiceImpl">
<constructor-arg index="0" ref="userDao"/>
<constructor-arg index="1" value="defaultValue"/>
<constructor-arg index="2" type="java.lang.String" value="typeSpecified"/>
</bean>
| 屬性 | 作用 |
|---|---|
| index | 參數位置索引(從 0 開始),解決同類型參數歧義 |
| type | 參數全限定類名,解決同類型參數歧義 |
| name | 參數名(需啟用 -parameters 編譯選項或 JDK 8+) |
| 維度 | 構造器注入 | Setter 注入 |
|---|---|---|
| 不可變性 | 支持 final 字段,構造後不可變 | 字段可變,需額外檢查 |
| 強依賴表達 | 天然表達「無此依賴無法工作」 | 需文檔約定 |
| 循環依賴 | 容器啟動時報錯,暴露設計缺陷 | 容器可通過早期暴露引用解決(有隱患) |
| 可選依賴 | 不友好,需重載構造器 | 天然支持 |
| 繼承友好 | 子類需調用 super(),參數傳遞繁瑣 | 子類無感知 |
Spring 4.3+ 支持單構造器隱式注入:若 Bean 只有一個構造器,無需 @Autowired 也會自動注入。推薦構造器注入作為首選,配合 Lombok @RequiredArgsConstructor 生成構造器,實現不可變、線程安全、易測試的服務類。
// 命名空間
<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"
xmlns:aop="https://www.springframework.org/schema/aop"
xsi:schemaLocation="...">
<context:component-scan base-package="cn.service"/> // 掃描註解 Bean
<context:property-placeholder location="classpath:jdbc.properties"/> // 屬性佔位符
<aop:aspectj-autoproxy/> // 啟用 @AspectJ
<tx:annotation-driven/> // 啟用 @Transactional
Spring 核心三板斧:IOC 容器管理對象生命週期、DI 實現鬆耦合裝配、AOP 分離橫切邏輯。構造器注入配合最終字段,構建健壯的領域服務;聲明式事務與緩存讓業務代碼專注核心邏輯。理解原理、掌握配置、遵循最佳實踐,是 Spring 開發者的必修課。