Spring 容器的核心職責是Bean 生命週期管理與依賴注入 (DI)。掌握 setter、constructor、field 三大注入方式、自動裝配四種模式、集合類型注入、依賴檢查、初始化/銷毀回調,是 Spring 開發者的必修課。本文系統性整理 Spring Bean 管理完整知識體系 (基於 Spring 5.x / Spring Boot 2.x+)。
<bean id="helloBean" class="com.example.HelloBean">
<property name="message" value="Hello Setter!"></property>
<property name="count" value="100"></property>
</bean>
public class HelloBean {
private String message;
private int count;
// 必須提供 setter
public void setMessage(String message) { this.message = message; }
public void setCount(int count) { this.count = count; }
}
特點:可讀性好、支援選填依賴、可重新綁定、需無參建構子
<bean id="helloBean" class="com.example.HelloBean">
<constructor-arg index="0" value="Hello Constructor!"></constructor-arg>
<constructor-arg index="1" value="200"></constructor-arg>
</bean>
public class HelloBean {
private final String message; // final 不可變
private final int count;
public HelloBean(String message, int count) {
this.message = message;
this.count = count;
}
// 無 setter 也能注入
}
特點:不可變物件、強制依賴、循環依賴早期發現、易於單元測試 (無 Spring 也能 new)
@Component
public class HelloBean {
@Autowired // 或 @Value("${config.value}")
private String message;
@Autowired
private OtherBean otherBean;
}
⚠️ 缺點:無法在無 Spring 環境下單元測試、隱藏依賴關係、不可用於 final 欄位、循環依賴難發現
✅ 建議:優先使用建構子注入,必要時輔以 Setter 注入 (選填依賴)
| 模式 | XML 屬性 | 匹配規則 | 適用場景 |
|---|---|---|---|
| byName | autowire="byName" | 屬性名 = Bean ID | 命名規範嚴謹的專案 |
| byType | autowire="byType" | 屬性類型 = Bean 類型 (唯一) | 單一實作類、介面唯一實作 |
| constructor | autowire="constructor" | 建構子參數類型匹配 | 建構子注入場景 |
| autodetect | autowire="autodetect" | 先試 constructor 再試 byType | 遺專案遷移 |
@Autowired
@Qualifier("specialDataSource") // byName 精確指定
private DataSource dataSource;
@Autowired // byType (若多個實作需加 @Qualifier)
private UserService userService;
<bean id="collectionBean" class="com.example.CollectionBean">
<!-- List 注入 -->
<property name="stringList">
<list>
<value>Item1</value>
<value>Item2</value>
<ref bean="otherBean"/>
</list>
</property>
<!-- Set 注入 (去重) -->
<property name="stringSet">
<set>
<value>A</value>
<value>B</value>
<value>A</value> <!-- 重複會被忽略 -->
</set>
</property>
<!-- Map 注入 -->
<property name="configMap">
<map>
<entry key="url" value="jdbc:mysql://..."/>
<entry key="poolSize" value="20"/>
<entry key="dataSource" value-ref="dataSource"/>
</map>
</property>
<!-- Properties 注入 -->
<property name="props">
<props>
<prop key="hibernate.dialect">MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<!-- 數組注入 -->
<property name="stringArray">
<array>
<value>arr1</value>
<value>arr2</value>
</array>
</property>
</bean>
public class CollectionBean {
private List stringList;
private Set stringSet;
private Map configMap;
private Properties props;
private String[] stringArray;
// Getter/Setter...
}
<bean id="helloBean" class="com.example.HelloBean"
dependency-check="objects"> <!-- 可選:simple, objects, all, none(default) -->
<property name="message" value="Hello"/>
</bean>
| 模式 | 檢查範圍 |
|---|---|
| none | 不檢查 (預設) |
| simple | 基本類型、String、基本類型包裝類 |
| objects | 物件引用類型 (協作 Bean) |
| all | 所有屬性 |
現代替代:@Required (已棄用) → 建構子注入天然強制依賴 + @NonNull (JSR-305) + 單元測試
實例化 → 屬性填充 → 初始化 → 使用中 → 銷毀 │ │ │ │ │ ├─ @PostConstruct / init-method │ │ ├─ InitializingBean.afterPropertiesSet() │ │ └─ BeanPostProcessor.postProcessBefore/AfterInitialization() │ │ │ └─ @Autowired / @Value / XML property │ └─ 建構子 / 工廠方法
@PostConstruct (JSR-250,推薦,標準化)implements InitializingBean → afterPropertiesSet() (Spring 耦合)init-method="init" / Java Config @Bean(initMethod="init")@PreDestroy (JSR-250,推薦)implements DisposableBean → destroy()destroy-method="cleanup" / @Bean(destroyMethod="cleanup")@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
@PostConstruct
public void init() {
System.out.println("1. @PostConstruct 初始化");
}
@Override
public void afterPropertiesSet() {
System.out.println("2. InitializingBean.afterPropertiesSet()");
}
@PreDestroy
public void cleanup() {
System.out.println("1. @PreDestroy 銷毀");
}
@Override
public void destroy() {
System.out.println("2. DisposableBean.destroy()");
}
}
| 作用域 | 說明 | Web 環境 |
|---|---|---|
| singleton | 容器中單一實例 (預設) | ✓ |
| prototype | 每次請求建立新實例 | ✓ |
| request | 每個 HTTP 請求一個實例 | 僅 Web |
| session | 每個 HTTP Session 一個實例 | 僅 Web |
| application | 每個 ServletContext 一個實例 | 僅 Web |
| websocket | 每個 WebSocket 會話一個實例 | 僅 Web |