BeanPostProcessor,是bean的增强器,在bean初始化前后调用,常用的方法有postProcessBeforeInitialization和postProcessAfterInitialization,在Spring启动并初始化bean前后通过它们做一些扩展操作。
1、BeanPostProcessor 接口说明
BeanPostProcessor接口在org.springframework.beans.factory.config包下,该接口源码如下:
public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
} 
名词解释:
- @Nullable:该注解可用在属性、方法、方法参数上,表示属性值、方法返回值、方法参数值可为空;
 - bean:指容器中正在创建的bean引用;
 - beanName:指容器中正在创建的bean名称;
 - postProcessBeforeInitialization():可理解为前置处理器,在bean初始化之前被调用;
 - postProcessAfterInitialization():可理解为后置处理器,在bean初始化之后被调用;
 
执行时机:
当创建bean实例并完成属性填充之后,会调用AbstractAutowireCapableBeanFactory类的initializeBean方法对bean进行初始化,在初始化前后会分别执行postProcessBeforeInitialization方法和postProcessAfterInitialization,源码如下:

继续打开看一看applyBeanPostProcessorsBeforeInitialization方法或applyBeanPostProcessorsAfterInitialization方法,如下:

这里,能看到BeanPostProcessor会对Spring容器的所有bean进行处理。
有了对BeanPostProcessor接口的认识,就可以通过它做一些逻辑扩展了。
2、BeanPostProcessor 应用场景
插件管理器
顾名思义,就是不同功能的插件需要在一个地方进行统一管理,也可以看作是设计模式中的策略模式。接下来,演示使用BeanPostProcessor实现一个插件管理器。
第一步,自定义一个BeanPostProcessor的实现类,即插件管理类PluginManager,如下:
/**
 * 插件管理器
 */
@Slf4j
@Component
public class PluginManager implements BeanPostProcessor {
    //定义一个数据处理器Map,用于存储和数据类型绑定的数据处理器对象
    private static final Map<String, DataProcessor> dataProcessorMap = new HashMap<>();
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, @Nullable String beanName) throws BeansException {
        if (bean instanceof DataProcessor) {
            DataProcessor dp = (DataProcessor) bean;
            dataProcessorMap.put(dp.getDataType(), dp);
            log.info("PluginManager.postProcessAfterInitialization() | size={},dataProcessorMap={}"
                    , dataProcessorMap.size(), dataProcessorMap);
        }
        return bean;
    }
    public static DataProcessor getDataPlugin(String dataType) {
        return dataProcessorMap.get(dataType);
    }
} 
注意,当Spring bean初始化之后,接着会调用postProcessAfterInitialization方法,我们利用该方法就可以做一些扩展增强操作。这里,将bean引用进行了具体化,即强转为某个对象,然后把与数据类型绑定的该对象实例存储到map里,并向外暴露一个静态的getDataPlugin方法,用于根据数据类型匹配到不同数据处理器对象。
第二步,自定义DataProcessor接口,提供一些方法给该接口的实现类们使用,如下:
/**
 * 数据处理器
 */
public interface DataProcessor {
    //获取数据类型
    String getDataType();
    
    //实现对应数据类型的业务处理逻辑
    void process(String var1, String var2)
} 
第三步,自定义DataProcessor接口的实现类TestAProcessor,并通过注解@Component注入容器,如下:
@Slf4j
@Component
public class TestAProcessor implements DataProcessor{
    @Override
    public String getDataType() {
        return "01";
    }
    @Override
    public void process(String var1, String var2) {
        //当前插件对应的业务逻辑 TODO
    }
} 
这里,我们按照该形式可以定义多个实现类(插件),我又增加了两个插件TestBProcessor和TestCProcessor,接着启动Spring容器做一些简单的测试,启动日志信息如下:

可以看到,当这些bean完成初始化之后,会走到postProcessAfterInitialization方法,通过该方法的扩展逻辑将这些bean与具体的数据类型绑定并存储在map里,从而达到了管理插件的目的。
第四步,根据不同的数据类型匹配对应的插件,统一入口如下:
public class PluginClass{
    public void demo() {
        String dataType = "01";
        //根据dataType匹配
        DataProcessor dataPlugin 
            = PluginManager.getDataPlugin(dataType);
        //插件实现的处理逻辑
        dataPlugin.process("", "");
    }
} 
这样就实现了插件管理的目的了。



















