小工具知识网

当前位置: 首页 > 行业知识 > Spring之BeanPostProcessor

行业知识

Spring之BeanPostProcessor

2026-11-12 04:52:09 来源:互联网转载

什么是BeanPostProcessor

BeanPostProcessor从本质上讲也是一个bean,它的实例化在普通bean之前,然后作用于普通bean。BeanPostProcessor可以作用于普通bean生命周期的以下几个阶段:

  • postProcessBeforeInitialization
  • postProcessAfterInitialization
  • postProcessBeforeInstantiation
  • postProcessAfterInstantiation
  • postProcessPropertyValues
  • postProcessMergedBeanDefinition
  • ......

    BeanPostProcessor实例化时机及排序问题

    AbstractApplicationContext#refresh

    具体实例化BeanPostProcessor的方法为registerBeanPostProcessors,该方法中有很多重复代码,大体可以分为查找、排序、注册三个阶段。具体排序规则如下:

    1. 实现了 PriorityOrdered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
    2. 实现了 Ordered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
    3. 未实现了 PriorityOrdered、Ordered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
    4. 实现了 PriorityOrdered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
    5. 实现了Ordered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
    6. 未实现了 PriorityOrdered、Ordered 接口实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor

    Spring默认注册的一些BeanPostProcessor

    BeanPostProcessor对普通bean生命周期的影响

    1.InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation

    AbstractAutowireCapableBeanFactory#createBean

    我们看一下注释:给bpp一个机会返回一个代理的对象,这很显然是一个扩展点,我们点进去看看究竟

    只要完成上述这三个条件,就不用执行后面的实例化流程了。比如属性填充(populateBean),方法回调等。

    自定义一些组件,满足上述三个条件
    创建一个普通类ModelJ ,类上标记@Component注解
    package com.test.spring.model;import org.springframework.stereotype.Component;@Componentpublic class ModelJ {}
    创建一个实现ApplicationContextAware接口和使用@Autowired注入属性的类
    package com.test.spring.model;import org.springframework.beans.BeansException;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;@Componentpublic class ModelI implements ApplicationContextAware {    @Autowired    private ModelJ modelJ;    private ApplicationContext applicationContext;    @Override    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {        this.applicationContext = applicationContext;    }}
    创建配置类AppConfig
    package com.test.spring.config;import org.springframework.context.annotation.ComponentScan;/** * 这里可以不用加@Configuration * AnnotationConfigApplicationContext会将构造方法注入的类,解析成bd */@ComponentScan("com.test.spring")public class AppConfig {}
    创建一个BeanFactoryPostProcessor
    @Componentpublic class SeventhBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {    @Override    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {        if (registry.containsBeanDefinition("modelI")) {            // 这里是ScannedGenericBeanDefinition 还不能强转成RootBeanDefinition            ScannedGenericBeanDefinition scannedGenericBeanDefinition = (ScannedGenericBeanDefinition) registry.getBeanDefinition("modelI");            RootBeanDefinition beanDefinition = new RootBeanDefinition();            beanDefinition.setBeanClassName(scannedGenericBeanDefinition.getBeanClassName());            try {                // 这个属性是包可见,利用反射强行设置了一下                Field beforeInstantiationResolved = beanDefinition.getClass().getDeclaredField("beforeInstantiationResolved");                beforeInstantiationResolved.setAccessible(true);                beforeInstantiationResolved.set(beanDefinition, true);            } catch (Exception e) {                throw new RuntimeException(e);            }            registry.registerBeanDefinition("modelI", beanDefinition);        }    }    @Override    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {    }}

    该BeanFactoryPostProcessor将BeanDefinition对象的 beforeInstantiationResolved 属性值修改为true,满足第一条件

    创建一个BeanPostProcessor
    package com.test.spring.bpp;import com.test.spring.model.ModelI;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Component;@Componentpublic class FirstBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {    @Override    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) {        if (beanClass == ModelI.class) {            try {                ModelI modelI = (ModelI) beanClass.newInstance();                return modelI;            } catch (Exception e) {                throw new RuntimeException(e);            }        } else {            return SmartInstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);        }    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        // 这个父类方法就是返回原对象,直接使用父类方法        return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);    }}

    该BeanPostProcessor的postProcessBeforeInstantiation方法,返回一个非空的值,满足第二条件。同时该BeanPostProcessor的postProcessAfterInitialization方法直接调用父类对象(该父类方法直接返回原对象),满足第三条件

    运行main方法,查看运行结果

    我们可以观察到属性注入方法(populateBean)和 回调方法(setApplicationContext)都没有执行,spring在执行完BeanPostProcessor的postProcessAfterInitialization方法后,就直接返回了 

    2. MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

    这个类我们拿其子类 AutowiredAnnotationBeanPostProcessor 举例

    AutowiredAnnotationBeanPostProcessor主要是查找所有bean中的注入点,随后在spring生命周期的某个节点将查找到的注入点,注入到指定的bean中

    Spring如何定义注入点

    简单来说,就是方法或者属性上存在@Autowired注解

    举例演示
    创建一个类ModelK
    package com.test.spring.model;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class ModelK {    @Autowired    private ModelI modelI;    private ModelJ modelJ;    @Autowired    public void setModelJ(ModelJ modelJ) {        this.modelJ = modelJ;    }}
    运行main方法,查看运行结果
    3.InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

    这个类在populateBean方法中,如果方法返回false,表示这个bean不执行属性填充操作

    举例演示
    创建一个类ModelL
    package com.test.spring.model;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;@Componentpublic class ModelL {    @Autowired    private ModelJ modelJ;}
    创建一个BeanPostProcessor
    package com.test.spring.bpp;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;import org.springframework.stereotype.Component;@Componentpublic class SecondBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {    @Override    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {        if ("modelL".equals(beanName)) {            return false;        } else {            return SmartInstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);        }    }}
    运行main方法,查看运行结果

    忽略注入属性modelJ

    4.BeanPostProcessor#postProcessBeforeInitialization

    这个方法前后及其子类实现,一般都是一些钩子函数,简单罗列一下

    • 方法之前
      • AbstractAutowireCapableBeanFactory#invokeAwareMethods
        • setBeanName
        • setBeanClassLoader
        • setBeanFactory
    • 子类实现
      • InitDestroyAnnotationBeanPostProcessor$LifecycleElement
        • @PostConstruct标注的方法
      • ApplicationContextAwareProcessor#invokeAwareInterfaces
        • setEnvironment
        • setEmbeddedValueResolver
        • setResourceLoader
        • setApplicationEventPublisher
        • setMessageSource
        • setApplicationStartup
        • setApplicationContext
    • 方法之后
      • AbstractAutowireCapableBeanFactory#invokeInitMethods
        • 处理实现InitializingBean接口的bean
      5.BeanPostProcessor#postProcessAfterInitialization

      在这一阶段,最常见的作用就是动态代理。比如@EnableTransactionManagement注解会注入一个类型为 InfrastructureAdvisorAutoProxyCreator 的BeanPostProcessor,这个类的祖父类(AbstractAutoProxyCreator)的方法实现(postProcessAfterInitialization)就是对满足条件的bean进行动态代理。相关源码如下:

       PS : @EnableAspectJAutoProxy注解和@EnableAsync注解注入的BeanPostProcessor,也会在这一阶段对满足条件的bean进行动态代理

      总结

      BeanPostProcessor的作用很强大,但是也很危险,如果不加条件判断要处理的特定bean,所有的bean的都会受影响,所有的bean的都会受影响,所有的bean的都会受影响,重要的事情说三遍。

上一篇:服务器怎么调披风?

下一篇:Rand源码深度解析,揭秘随机数生成的神秘面纱