BeanPostProcessor 的用法

BeanPostProcessor 的用法

BeanPostProcessor 是 Spring 对外提供的一个扩展,用于在 bean 初始化阶段对 bean 做一些特殊的处理。

BeanPostProcessor 的定义及作用

public interface BeanPostProcessor {

    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor 中定义两个方法,postProcessBeforeInitializationpostProcessAfterInitialization,调用时机分别是在 bean 被初始化之后,继承自 InitializingBeanafterPropertiesSet 方法或者 xml 文件中定义的 init-method 方法被调用之前,而 postProcessAfterInitialization 是在这种 callback 方法被调用之后执行。

如下图所示(上没法解析有道云的流程图语法):

graph TD
A[Bean 实例化/ 设置属性 / 回调 Aware 等操作] --> B[调用 postProcessBeforeInitialization]
B --> C[调用 afterPropertiesSet / init-method 等回调方法]
C --> D[调用 postProcessAfterInitialization 方法]
D --> E[其他操作...]

BeanPostProcessor 的源码分析

bean 的初始化是在 refresh 方法中进行的,首先将 BeanPostProcessor 注册到 BeanFactory 中,在执行 initializeBean 的时候再调用,注册是在 registerBeanPostProcessors(beanFactory) 进行的:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

继续查看 registerBeanPostProcessors 方法:

    public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

        // 获取所有的 BeanPostProcessor bean 名字
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // ...

        // 根据不同的优先级,内部 processor 以及 Order 排序,再处理
        List priorityOrderedPostProcessors = new ArrayList<>();
        List internalPostProcessors = new ArrayList<>();
        List orderedPostProcessorNames = new ArrayList<>();
        List nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // 先注册实现了 PriorityOrdered 接口的
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        List orderedPostProcessors = new ArrayList<>();
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        // 再注册实现了 Ordered 接口的
        sortPostProcessors(orderedPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // 然后注册没有指定优先级的
        List nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // 最后注册内部的
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // 最后添加一个 Spring 自带的
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }

在 bean 初始化时候调用 postProcessBeforeInitializationpostProcessAfterInitialization

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        // 处理 Aware
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }
        // 先调用 postProcessBeforeInitialization
        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
        // 再调用 afterPropertiesSet / init-method 等回调方法
        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        // 最后调用 postProcessAfterInitialization
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

BeanPostProcessor 的应用场景

Spring 内部使用 BeanPostProcessor 来进行 bean 的增强,比如 AOP,Dubbo 中也使用 BeanPostProcessor 来实现 @Reference 注解的对象注入。

在我做过的项目中,使用 BeanPostProcessor 进行了和 Dubbo 类似的操作,对自定义注解进行了注入,比如定义了一个 @Person 注解,在 postProcessBeforeInitialization 中读取传入的 bean 是不是符合要求的,如果是符合要求的,注入一个自定义的对象到 bean 中标注了 @Person 注解的属性中。

你可能感兴趣的:(BeanPostProcessor 的用法)