<beans>
<bean id="foo" class="com.xidian.Foo" /> <!-- 最簡配置:id + 全限定類名 -->
</beans>
| Scope | 含義 | 適用場景 |
|---|---|---|
| singleton (默認) | 容器內單例,全局共享 | 無狀態 Service、DAO、工具類 |
| prototype | 每次獲取創建新實例 | 有狀態對象、命令模式、請求級 Bean |
| request | 每個 HTTP 請求一個實例 | Web 環境,表單對象 |
| session | 每個 HTTP Session 一個實例 | 用戶購物車、偏好設置 |
| globalSession | Portlet 全局 Session | Portlet 環境 |
最佳實踐:優先 singleton,prototype 慎用(性能、GC 壓力)。
<bean id="car" class="com.example.Car">
<property name="engine" ref="engine" /> <!-- ref 引用另一 bean -->
</bean>
<bean id="engine" class="com.example.Engine" />
<bean id="car" class="com.example.Car">
<property name="engine">
<bean class="com.example.Engine" /> <!-- 無 id,外部不可引用 -->
</property>
</bean>
<bean id="student" class="com.example.Student">
<property name="name" value="順平" />
<property name="age" value="30" />
</bean>
<bean id="graduate" parent="student" class="com.example.Graduate">
<property name="degree" value="碩士" /> <!-- 覆蓋或新增 -->
</bean>
parent 屬性值為父 Bean 的 id,而非類名。
<property name="name">
<value>tom</value> <!-- 或 value="tom" 簡寫 -->
</property>
<bean id="dept" class="com.example.Department">
<!-- 數組 -->
<property name="empNames">
<list><value>小明</value><value>小紅</value></list>
</property>
<!-- List (可重復) -->
<property name="empList">
<list>
<ref bean="emp1" />
<ref bean="emp2" />
<ref bean="emp1" /> <!-- 允許重復 -->
</list>
</property>
<!-- Set (不可重復) -->
<property name="empSet">
<set>
<ref bean="emp1" />
<ref bean="emp2" />
</set>
</property>
<!-- Map -->
<property name="empMap">
<map>
<entry key="11" value-ref="emp1" />
<entry key="22" value-ref="emp2" />
</map>
</property>
<!-- Properties -->
<property name="props">
<props>
<prop key="k1">v1</prop>
<prop key="k2">v2</prop>
</props>
</property>
</bean>
public class Employee {
private String name;
private Integer age;
public Employee(String name, Integer age) { this.name = name; this.age = age; }
}
<bean id="employee" class="com.example.Employee">
<constructor-arg index="0" type="java.lang.String" value="大明" />
<constructor-arg index="1" type="java.lang.Integer" value="22" />
</bean>
type="java.lang.Integer"(不可寫 int 或 Integer)。type="int"(不可寫 java.lang.Integer)。| 維度 | Setter 注入 | 構造器注入 |
|---|---|---|
| 必選依賴表達 | 無法強制(可選屬性易混淆) | 構造器參數天然表達強依賴 |
| 不可變對象 | 不支持(需 setter) | 支持(final 字段 + 構造器) |
| 循環依賴 | 支持(Set 後再注入) | 不支持(需 @Lazy 或 Setter 輔助) |
| 可讀性 | 屬性名清晰 | 參數順序易誤 |
| 主流建議 | ✅ 通用首選 | ✅ 必選依賴/不可變對象首選 |
<bean id="master" class="com.example.Master" autowire="byName" />
<bean id="dog" class="com.example.Dog" /> <!-- id=dog 匹配 master 的 dog 屬性 -->
| 模式 | 匹配規則 | 風險 |
|---|---|---|
| byName | 屬性名 = Bean id | 重命名屬性/Bean 易斷裂 |
| byType | 屬性類型 = Bean 類型(唯一) | 多實現拋異常 |
| constructor | 構造器參數類型匹配 | 同 byType |
| autodetect | 優先 constructor,失敗回退 byType | 不可控 |
<beans default-autowire="byName"> <!-- 全局默認 -->
<bean id="foo" class="..." autowire="default" /> <!-- 繼承全局 -->
</beans>
建議:生產環境禁用自動裝配,顯式 <property>/<constructor-arg> 更清晰、可追蹤、重構安全。
<context:property-placeholder location="classpath:db.properties,classpath:db2.properties" />
# db.properties
name=scott
drivername=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:hsp
pwd=tiger
# db2.properties
db2.name=sys
db2.drivername=...
db2.url=...
db2.pwd=...
${key}<bean id="dbutil" class="com.example.DBUtil">
<property name="name" value="${name}" />
<property name="drivername" value="${drivername}" />
<property name="url" value="${url}" />
<property name="pwd" value="${pwd}" />
</bean>
<bean id="dbutil2" class="com.example.DBUtil">
<property name="name" value="${db2.name}" />
<property name="drivername" value="${db2.drivername}" />
<property name="url" value="${db2.url}" />
<property name="pwd" value="${db2.pwd}" />
</bean>
需要裝配 Bean
│
├─ 強依賴 / 不可變對象 / final 字段 ──→ 構造器注入 (constructor-arg)
│
├─ 可選依賴 / 可變對象 / 多屬性 ──→ Setter 注入 (property)
│
├─ 大量相似 Bean / 快速原型 ──→ 自動裝配 (autowire) ⚠️ 僅開發期
│
├─ 多環境配置 / 敏感信息外部化 ──→ 屬性佔位符 (${}) + PropertyPlaceholder
│
└─ 集合/Map/Props 注入 ──→ property + list/set/map/props 標籤
掌握 Spring Bean 裝配的各種方式、適用邊界與避坑指南,能構建清晰、可維護、環境友好的 IoC 容器配置。