Spring cung cấp khả năng tùy chỉnh mạnh mẽ thông qua các giao diện mở rộng, cho phép can thiệp vào vòng đời của bean. Hai giao diện phổ biến nhất là InitializingBean và DisposableBean, giúp thực hiện logic bổ sung sau khi bean được khởi tạo hoặc trước khi bị hủy.
Giao diện InitializingBean
Giao diện này yêu cầu triển khai phương thức afterPropertiesSet(), được gọi ngay sau khi tất cả thuộc tính của bean đã được tiêm (inject). Đây là nơi lý tưởng để thực hiện các bước khởi tạo bắt buộc trước khi bean sẵn sàng sử dụng.
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
Giao diện DisposableBean
Khi bean chuẩn bị bị loại bỏ khỏi container, phương thức destroy() sẽ được gọi để dọn dẹp tài nguyên, đóng kết nối, hoặc thực hiện các tác vụ cuối cùng.
public interface DisposableBean {
void destroy() throws Exception;
}
Thứ tự thực thi trong vòng đời bean
Khi một bean được khởi tạo, Spring tuân theo trình tự sau:
- Gọi constructor để tạo đối tượng
- Thực hiện dependency injection (gán giá trị cho các thuộc tính)
- Gọi
afterPropertiesSet()nếu bean implementsInitializingBean - Gọi phương thức khởi tạo tùy chỉnh (
init-method) nếu có cấu hình
Khi bean bị hủy:
- Gọi
destroy()nếu bean implementsDisposableBean - Gọi phương thức hủy tùy chỉnh (
destroy-method) nếu có cấu hình
Ví dụ minh họa
public class DataProcessor implements InitializingBean, DisposableBean {
private DataSource dataSource;
public DataProcessor() {
System.out.println("Khởi tạo đối tượng");
}
@Override
public void afterPropertiesSet() {
System.out.println("Hoàn tất thiết lập thuộc tính - chuẩn bị kết nối dữ liệu");
}
@Override
public void destroy() {
System.out.println("Đóng kết nối dữ liệu");
}
public void customInit() {
System.out.println("Phương thức khởi tạo tùy chỉnh");
}
public void customDestroy() {
System.out.println("Phương thức dọn dẹp tùy chỉnh");
}
// Getter & Setter
public void setDataSource(DataSource ds) {
this.dataSource = ds;
System.out.println("Tiêm phụ thuộc DataSource");
}
}
Cấu hình trong XML:
<bean id="processor"
class="com.example.DataProcessor"
init-method="customInit"
destroy-method="customDestroy">
<property name="dataSource" ref="dataSource"/>
</bean>
Kết quả khi chạy:
Khởi tạo đối tượng
Tiêm phụ thuộc DataSource
Hoàn tất thiết lập thuộc tính - chuẩn bị kết nối dữ liệu
Phương thức khởi tạo tùy chỉnh
...
Đóng kết nối dữ liệu
Phương thức dọn dẹp tùy chỉnh
Cơ chế bên trong
Spring xử lý việc gọi các phương thức vòng đời thông qua lớp AbstractAutowireCapableBeanFactory. Khi khởi tạo bean, phương thức invokeInitMethods được gọi để kiểm tra và thực thi afterPropertiesSet trước, sau đó mới đến init-method.
Tương tự, khi hủy bean, Spring sử dụng DisposableBeanAdapter để bao bọc bean và gọi destroy() trước, rồi mới gọi destroy-method thông qua reflection.
Mỗi bean cần dọn dẹp sẽ được đăng ký vào map disposableBeans trong quá trình khởi tạo, đảm bảo rằng khi container shutdown, tất cả tài nguyên đều được giải phóng đúng cách.
Lưu ý quan trọng
- Nếu
afterPropertiesSet()ném exception, phương thứcinit-methodsẽ không được thực thi. - Cách tiếp cận qua giao diện hiệu quả hơn do không dùng reflection, nhưng làm mã nguồn phụ thuộc vào API Spring.
- Dùng
init-method/destroy-methodlinh hoạt hơn, tách rời framework, nhưng chậm hơn do dùng reflection.