BeanPostProcessor是bean的后置处理器,会影响bean的一些行为甚至是替换原有的bean。了解BeanPostProcessor之前最好有对BeanFactoryPostProcessor有一些了解,不了解的小伙伴可以查看我的上篇博文Spring之BeanFactoryPostProcessor
BeanPostProcessor从本质上讲也是一个bean,它早于其他普通bean之前实例化,然后作用于其他普通bean,我们看一下Spring源码中实例化时机
具体源码在AbstractApplicationContext#refresh方法中

我们可以看到BeanPostProcessor早于普通bean的实例化时机,所以可以对普通bean进行处理,后文我将BeanPostProcessor简称为bpp
这个registerBeanPostProcessors对bpp的处理,和Spring对bfpp的处理很像,我在这里贴一下之前整理的处理顺序
我们看一下AbstractAutowireCapableBeanFactory#createBean方法

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

我们看到只要我们完成这三个条件,就不用执行后面的实例化流程了,比如说填充属性的方法(populateBean),各种回调方法,比如ApplicationContextAware, InitializingBean
我们来自定义一个bpp,来满足上述条件,看看结果是否符合预期
创建一个普通的类,标记上@Component注解,会被扫描生成bd对象
package com.test.spring.model;
import org.springframework.stereotype.Component;
@Component
public 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;
@Component
public class ModelI implements ApplicationContextAware {
@Autowired
private ModelJ modelJ;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
创建一个配置类
package com.test.spring.config;
import org.springframework.context.annotation.ComponentScan;
/**
* 这里可以不用加@Configuration
* AnnotationConfigApplicationContext会将构造方法注入的类,解析成bd
*/
@ComponentScan("com.test.spring")
public class AppConfig {
}
@Component
public 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) {
}
}
创建一个bpp 指定其postProcessBeforeInstantiation方法返回值(满足第二条件),postProcessAfterInitialization就直接使用父类方法,返回原对象(满足第三条件)
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;
@Component
public 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);
}
}
运行main方法 查看结果
我们可以看到属性注入方法(populateBean)和回调方法(setApplicationContext)都没有执行,Spring处理完bpp的postProcessAfterInitialization方法,就直接返回了
这个类我们拿其子类AutowiredAnnotationBeanPostProcessor举例
AutowiredAnnotationBeanPostProcessor主要是查找所有bean中的注入点,后面在某个时间点将查找的注入点注入到bean中
我们看一下Spring源码怎么定义注入点

简单来说就是方法或者属性上面加了@Autowired注解就是注入点后期会在某个时间点注入,我们写个简单的例子来看一下
创建一个类ModelK
package com.test.spring.model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ModelK {
@Autowired
private ModelI modelI;
private ModelJ modelJ;
@Autowired
public void setModelJ(ModelJ modelJ) {
this.modelJ = modelJ;
}
}
运行main方法 查看结果
注入点都注入到bean中了
这个类在populateBean方法中,如果方法返回false就表示这个bean 不填充properties了

我们写一个简单例子看一下
创建一个类ModelL
package com.test.spring.model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ModelL {
@Autowired
private ModelJ modelJ;
}
创建一个bpp
package com.test.spring.bpp;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public 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忽略注入了
这个方法前后一般执行了钩子函数 罗列一下
在这个方法之前
AbstractAutowireCapableBeanFactory#invokeAwareMethods
相关子类实现
InitDestroyAnnotationBeanPostProcessor$LifecycleElement
ApplicationContextAwareProcessor
在这个方法之后
AbstractAutowireCapableBeanFactory#invokeInitMethods
@EnableTransactionManagement注解我们经常使用,应该会很熟悉,其实它的原理就是注入了一个bfpp(AbstractAutoProxyCreator的一个子类,但是子类没有重写postProcessAfterInitialization方法,所以相关逻辑还是在AbstractAutoProxyCreator类中),这个bfpp的重要作用就是动态代理,我们来看相关代码

bpp的作用很强大,但是也很危险,如果不加条件判断要处理的特定bean,所有的bean的都会受影响,所有的bean的都会受影响,所有的bean的都会受影响,重要的事情说三遍。而且这种错误很不容易发现,必须在一个个bpp中debug,所以使用前要做到谨慎再谨慎