1. BeanPostProcessor

1.1 doc

文档说明:

  • 官网 doc
  • api doc

    Factory hook that allows for custom modification of new bean instances — for example, checking for marker interfaces or wrapping beans with proxies. Typically, post-processors that populate beans via marker interfaces or the like will implement postProcessBeforeInitialization(java.lang.Object, java.lang.String), while post-processors that wrap beans with proxies will normally implement postProcessAfterInitialization(java.lang.Object, java.lang.String).

描述实在太长了,这里就不贴了,大家自己去上面可以阅读下哈。

下面概述总结下:
BeanPostProcessor 是一个容器的扩展点,它可以在 bean 的生命周期过程中,初始化阶段前后添加自定义处理逻辑,并且不同 IOC 容器间的 BeanPostProcessor 不会相互干预。

1.2 使用

  1. @Component
  2. public class TestBeanPostProcessor implements BeanPostProcessor {
  3. @Override
  4. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  5. System.out.println("拦截到Bean的初始化之前:" + beanName);
  6. return bean;
  7. }
  8. @Override
  9. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  10. System.out.println("拦截到Bean的初始化之后:" + beanName);
  11. return bean;
  12. }
  13. }
  • 如果 return null 也能正常返回,是因为 Spring BeanPostProcessor 的 postProcessBeforeInitialization 方法,是在 AbstractAutowireCapableBeanFactory 中被调用的,而其中有一层兜底策略。如果返回 null,仍会返回。
  • 大家可以运行下,可以得出和前面学过的例如 init 方法等的顺序:BeanPostProcessor#postProcessBeforeInitialization → @PostConstruct → InitializingBean → init-method → BeanPostProcessor#postProcessAfterInitialization

    • 就是下面这份代码 + 上面的 BeanPostProcessor
    • 这个顺序问题,后面到 Bean 的生命周期我们再细细看。

      1. public class Test implements InitializingBean {
      2. public void initMethod() {
      3. System.out.println("initMethod ...");
      4. }
      5. @PostConstruct
      6. public void postConstruct() {
      7. System.out.println("PostConstruct ...");
      8. }
      9. @Override
      10. public void afterPropertiesSet() throws Exception {
      11. System.out.println("InitializingBean ...");
      12. }
      13. }

      2. 扩展

      2.1 InstantiationAwareBeanPostProcessor

      方法:

  • postProcessBeforeInstantiation :在 bean 的实例化之前处理非常容易理解,它可以拦截 bean 原本的实例化方法,转为用这里的实例化

  • postProcessAfterInstantiation :在 bean 的实例化之后处理,如果返回 false ,则 postProcessProperties 方法不会执行
  • postProcessProperties :最终会返回一组属性和值的 PropertyValues ,让它参与 bean 的属性赋值环节

如果说我们刚才的执行顺序是这样的

① xxx -> ② Bean 实例化 -> ③ 属性赋值、自检自动注入 -> ④ 初始化方法回调(@PostConstruct 、InitializingBean、initMethod)-> ⑤ 完毕

BeanPostProcessor 的 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法是在 ④ 和 ⑤ 之间,那么 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 就是在 ① 和 ② 之间,而 postProcessAfterInstantiation 和 postProcessProperties (postProcessPropertyValues) 就是在 ② 和 ③ 之间,其实就是在 ② Bean 实例化 前后执行。

3. BeanFactoryPostProcessor

3.1 概述和使用

BeanFactoryPostProcessor 是容器的扩展点,它用于 IOC 容器的生命周期中,所有 BeanDefinition 都注册到 BeanFactory 后回调触发,用于访问 / 修改已经存在的 BeanDefinition 。与 BeanPostProcessor 相同,它们都是容器隔离的,不同容器中的 BeanFactoryPostProcessor 不会相互起作用。

  1. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  2. Stream.of(beanFactory.getBeanDefinitionNames()).forEach(beanName -> {
  3. BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
  4. if (StringUtils.hasText(beanDefinition.getBeanClassName())) {
  5. if (ClassUtils.resolveClassName(beanDefinition.getBeanClassName(), this.getClass().getClassLoader())
  6. .getSuperclass().equals(Color.class)) {
  7. beanDefinition.getPropertyValues().add("name", beanName);
  8. }
  9. }
  10. });
  11. }

3.2 BeanPostProcessor 和 BeanFactoryPostProcessor 的区别:

BeanPostProcessor BeanFactoryPostProcessor
处理目标 bean 实例 BeanDefinition
执行时机 bean 的初始化阶段前后(已创建出 bean 对象) BeanDefinition
解析完毕,注册进 BeanFactory
的阶段( bean 未实例化)
可操作的空间 给 bean 的属性赋值、创建代理对象等 BeanDefinition
中增删属性、移除 BeanDefinition

4. BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 是容器的扩展点,它用于 IOC 容器的生命周期中,所有 BeanDefinition 都准备好,即将加载到 BeanFactory 时回调触发,用于给 BeanFactory 中添加新的 BeanDefinition 。BeanDefinitionRegistryPostProcessor 也是容器隔离的,不同容器中的 BeanDefinitionRegistryPostProcessor 不会相互起作用。

  1. @Component
  2. public class TestRegisterPostProcessor implements BeanDefinitionRegistryPostProcessor {
  3. @Override
  4. public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
  5. if (!registry.containsBeanDefinition("dog")) {
  6. // 构造BeanDefinition,并注册进BeanFactory
  7. BeanDefinition dogDefinition = BeanDefinitionBuilder.genericBeanDefinition(Dog.class).getBeanDefinition();
  8. registry.registerBeanDefinition("dog", dogDefinition);
  9. }
  10. }
  11. @Override
  12. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  13. }
  14. }

5. 三者的区别

BeanPostProcessor BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor
处理目标 bean 实例 BeanDefinition BeanDefinition
.class
文件等
执行时机 bean 的初始化阶段前后(已创建出 bean 对象) BeanDefinition
解析完毕并注册进 BeanFactory
之后(此时 bean 未实例化)
配置文件、配置类已解析完毕并注册进 BeanFactory
,但还没有被 BeanFactoryPostProcessor
处理
可操作的空间 给 bean 的属性赋值、创建代理对象等 BeanDefinition
中增删属性、移除 BeanDefinition
BeanFactory
中注册新的 BeanDefinition