Trong Spring, khái niệm quan trọng nhất là IOC và AOP. AOP giúp mở rộng chức năng của mã nguồn bằng cách chèn thêm các đoạn mã vào trước hoặc sau khi thực thi các phương thức chính.
Khi cần mở rộng hoặc sửa đổi chức năng của các bean trong quá trình khởi tạo, Spring sử dụng khái niệm BeanPostProcessor. BeanPostProcessor là một giao diện cho phép thực hiện các tác vụ tùy chỉnh trước và sau khi các bean được khởi tạo.
1. Giao diện BeanPostProcessor
Giao diện BeanPostProcessor chỉ định hai phương thức:
public interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Khi Spring khởi tạo một bean, nó sẽ thực hiện các bước sau: tạo bean, tiêm phụ thuộc, và cuối cùng là khởi tạo bean. BeanPostProcessor hoạt động trong quá trình khởi tạo này.
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
invokeInitMethods(beanName, wrappedBean, mbd);
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
2. Sử dụng BeanPostProcessor
Ví dụ dưới đây minh họa việc tạo một BeanPostProcessor tùy chỉnh:
public class CustomBeanEnhancer implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Trước khi khởi tạo bean");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Sau khi khởi tạo bean");
if (beanName.endsWith("Service")) {
try {
System.out.println("Tạo lại bean thông qua newInstance()");
Class> clazz = bean.getClass();
bean = clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return bean;
}
}
Định nghĩa một lớp Service như sau:
public class ProductService {
private String productId;
public ProductService() {}
public ProductService(String productId) {
this.productId = productId;
}
public void init() {
System.out.println("Khởi tạo ProductService");
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
}
Cấu hình Spring để sử dụng BeanPostProcessor và các bean:
<bean id="productService" class="com.example.ProductService" init-method="init">
<constructor-arg value="PROD001"/>
</bean>
<bean id="customBeanEnhancer" class="com.example.CustomBeanEnhancer"/>
Khi chạy ứng dụng, kết quả sẽ như sau:
Trước khi khởi tạo bean
Khởi tạo ProductService
Sau khi khởi tạo bean
Tạo lại bean thông qua newInstance()
Trước khi khởi tạo bean
Khởi tạo ProductService
Sau khi khởi tạo bean
null
PROD001
3. Nguyên lý hoạt động của BeanPostProcessor
Sau khi khởi tạo Spring container, tất cả các BeanPostProcessor cũng được khởi tạo. Khi một bean được khởi tạo, Spring sẽ áp dụng các BeanPostProcessor đã đăng ký.
3.1 Đăng ký BeanPostProcessor
Phương thức addBeanPostProcessor trong AbstractBeanFactory được sử dụng để thêm BeanPostProcessor vào danh sách quản lý.
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
this.beanPostProcessors.remove(beanPostProcessor);
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
this.beanPostProcessors.add(beanPostProcessor);
}
3.2 Thực thi BeanPostProcessor
Khi khởi tạo bean, các BeanPostProcessor được áp dụng:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
applyMergedBeanDefinitionPostProcessors(mbd, instanceWrapper.getBeanClass(), beanName);
mbd.postProcessed = true;
}
}
populateBean(beanName, mbd, instanceWrapper);
Object exposedObject = instanceWrapper.getWrappedInstance();
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
4. Các giao diện con của BeanPostProcessor
4.1 InstantiationAwareBeanPostProcessor
Giống như BeanPostProcessor, nhưng cung cấp thêm các phương thức để xử lý trước và sau khi khởi tạo bean.
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
}
4.2 MergedBeanDefinitionPostProcessor
Dùng để xử lý sau khi hợp nhất định nghĩa bean.
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
default void resetBeanDefinition(String beanName) {}
}
4.3 SmartInstantiationAwareBeanPostProcessor
Kế thừa từ InstantiationAwareBeanPostProcessor và bổ sung thêm các phương thức để dự đoán loại bean và xác định các constructor.
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
@Nullable
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
return bean;
}
}
4.4 DestructionAwareBeanPostProcessor
Xử lý các tác vụ trước khi bean bị hủy.
public interface DestructionAwareBeanPostProcessor extends BeanPostProcessor {
void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
default boolean requiresDestruction(Object bean) {
return true;
}
}
5. Các BeanPostProcessor quan trọng trong Spring
5.1 AutowiredAnnotationBeanPostProcessor
Xử lý các chú thích như @Autowired.
5.2 CommonAnnotationBeanPostProcessor
Xử lý các chú thích như @Resource.
5.3 ApplicationContextAwareProcessor
Gọi các phương thức set trong các bean triển khai các giao diện Aware.