Spring BeanPostProcessor

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("", "");
    }
}

这样就实现了插件管理的目的了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值