Giải Thích Giao Diện Mở Rộng BeanPostProcessor trong Spring

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.

Thẻ: Spring BeanPostProcessor AOP ioc

Đăng vào ngày 16 tháng 6 lúc 05:25