BeanPostProcessor后置处理器原理与应用
BeanPostProcessor又叫后置处理器,是spring框架极其重要的概念。本身是个接口,接口里面定义了两个方法。许多扩展功能都是基于这种后置处理器的方式来实现的。spring框架会自动识别所有实现BeanPostProcessor接口的实现类,加载到容器中。当容器实例化完具体的一个bean后,会遍历所有实现接口的类,执行接口的实现方法,对刚刚实例化的bean进行初始化操作。
这只是最简单的应用,BeanPostProcessor还有几个子接口,可以实现在bean实例化前,后执行一些自定义操作。具体的用法和原理下面来分析。
1. BeanPostProcessor及相应子接口的应用
BeanPostProcessor就是为扩展,便于spring框架与其他应用整合。在容器内部和自定义的有很多子接口和实现类。这里介绍几个比较常用的子接口用法,具体的实现类太多,没办法一一介绍。
1.1 环境搭建
搭建一个spring环境,这里只是一个最基本的spring环境。
创建maven项目,依赖如下
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.10.RELEASE</version>
</dependency>
</dependencies>
使用java配置类的方式,创建一个启动类,一个用于测试的JavaBean和启动类
@Configuration
public class AppConfig {
@Bean
public User user()
{
return new User();
}
}
public class User {
private String name="li";
public User(String name) {
this.name = name;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
public class TestBean {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Object bean = context.getBean("user");
System.out.println(bean);
}
}
1.1 BeanPostProcessor接口应用
创建一个实现BeanPostProcessor的类
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof User) {
System.out.println("postProcessBeforeInitialization中的bean:" + bean);
User user = (User) bean;
user.setName("曹操");
return user;
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization中的bean:" + bean);
return bean;
}
}
在AppConfig配置类中添加配置将MyBeanPostProcessor注册容器中。
@Bean
public BeanPostProcessor beanPostProcessor() {
return new MyBeanPostProcess();
}
启动TestBean中的Main方法,输出结果
postProcessBeforeInitialization中的bean:User{name='li'}
postProcessAfterInitialization中的bean:User{name='曹操'}
User{name='曹操'}
由上面结果可以得出结论
- 容器会自动识别BeanPostProcessor的实现类,并自动调用
- 容器会在bean实例化以后,执行接口中的方法
- postProcessBeforeInitialization方法先执行,postProcessAfterInitialization后执行
- 确实可以修改bean的属性
1.2 InstantiationAwareBeanPostProcessor接口应用
InstantiationAwareBeanPostProcessor是BeanPostProcessor的子接口,在接口中增加了几个方法,创建一个InstantiationAwareBeanPostProcessor的实现类,并加入到容器中。BeanPostProcessor接口中的方法就不在重复实现了。
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("将beanName=user的bean类型改为Object,实例化");
if (beanName.equals("user")) {
return new Object();
}
return null;
}
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInstantiation执行");
return true;
}
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("postProcessProperties执行");
return null;
}
}
在AppConfig配置类中添加配置将MyInstantiationAwareBeanPostProcessor注册容器中。
@Bean
public InstantiationAwareBeanPostProcessor instantiationAwareBeanPostProcessor()
{
return new MyInstantiationAwareBeanPostProcessor();
}
启动TestBean中的Main方法,输出结果:
将beanName=user的bean类型改为Object,实例化
java.lang.Object@64d2d351
总结一下:
- InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation方法可以阻止bean正常实例化,甚至可以修改bean的类型,实际上spring的aop就是基于这个地方实现的
- postProcessAfterInstantiation方法实在bean实例化之后,初始化之前调用的。并且如果postProcessBeforeInstantiation方法返回的不是null,postProcessAfterInstantiation和postProcessProperties方法都不会执行。可以自行测试。
2. BeanPostProcessor实现原理
说清楚BeanPostProcessor的实现原理需要学习spring源码,至少要了解spring容器的启动过程和bean的加载流程。这里只说明BeanPostProcessor的原理,不涉及其他方面的,我们直接看相关的源码。
其实BeanPostProcessor实现原理包括两个主要过程:
- BeanPostProcessor的加载注册
- BeanPostProcessor方法调用
2.1 BeanPostProcessor的加载注册
BeanPostProcessor的加载注册在spring容器启动实现的,看具体实现代码,当执行AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);代码时,会启动容器,这个过程中会执行加载BeanPostProcessor的代码。具体的加载逻辑如下,代码在PostProcessorRegistrationDelegate类中。
调用链路:
new AnnotationConfigApplicationContext(AppConfig.class)
refresh()
registerBeanPostProcessors(beanFactory)
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this)
registerBeanPostProcessors
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//获取所有实现BeanPostProcessor接口的实现类的beanName
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//统计BeanPostProcessor的数量,包括内置的,上面查找到的,还有一个用于检查这些BeanPostProcessor的
//BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//BeanPostProcessor分类,按PriorityOrdered,Ordered,正常顺序加载
//实现按PriorityOrdered接口
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
//内部BeanPostProcessor
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
//实现按Ordered接口
List<String> orderedPostProcessorNames = new ArrayList<>();
//剩下的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
//BeanPostProcessor分类
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);//排序
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);//注册
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);//排序
registerBeanPostProcessors(beanFactory, orderedPostProcessors);//注册
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
总结一下流程:
-
找到所有实现BeanPostProcessor接口的实现类
-
将BeanPostProcessor分类,实现PriorityOrdered接口的先排序注册,然后是实现Ordered接口的,接着是正常的,最后是内部的,最后添加一个ApplicationListenerDetector。
-
保存BeanPostProcessor的是一个List,可以按顺序遍历的
2.2 BeanPostProcessor的调用
BeanPostProcessor接口以及子接口InstantiationAwareBeanPostProcessor在bean的加载过程中调用的。这里我们可以以Object bean = context.getBean(“user”);为入口来学习。实际上并不是在这里执行的,这里的“user”bean在容器启动的最后一步加载的,只是执行加载bean的逻辑是一致的。
Object bean = context.getBean(“user”);跟下去会执行AbstractBeanFactory类中的doGetBean方法,这个方法涉及的逻辑比较复杂,与BeanPostProcessor不相关,所以不会详细分析,只是知道接下来会执行AbstractAutowireCapableBeanFactory类的createBean方法即可。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args); //这里真正实例化bean
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
这个方法关注Object bean = resolveBeforeInstantiation(beanName, mbdToUse);这个方法上面有一个注释//Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.说的很清楚了,进入方法看一下。值得注意的是,如果执行这个逻辑返回的不是null,整个创建bean的流程就结束了,直接返回bean,不会走下面的流程。
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
这个方法主要做一些判断验证逻辑,真正执行的后置处理器的逻辑是bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);这里有一个逻辑,如果执行bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);返回了不是null,才会执行InstantiationAwareBeanPostProcessor中的另一个方法postProcessAfterInitialization,在bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);中被调用。
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
找到所有InstantiationAwareBeanPostProcessor实现对象,执行postProcessBeforeInstantiation方法。
如果上面的代码没有在Object bean = resolveBeforeInstantiation(beanName, mbdToUse);返回,会接续向下执行。在 Object beanInstance = doCreateBean(beanName, mbdToUse, args);真正的创建bean实例。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//这里其实也是一个后置处理器的子接口,在这调用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
在这里我们关注的是exposedObject = initializeBean(beanName, exposedObject, mbd);方法,提一句,当执行都这里时,bean已经被实例化,并且属性已经被装配完成。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这个方法执行初始化逻辑,关注三个方法;
-
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
-
invokeInitMethods(beanName, wrappedBean, mbd);
-
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
第一个和第三个方法就是执行BeanPostProcessor的连个方法,中间的进去看一下
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
这个方法是执行实现InitializingBean接口afterPropertiesSet方法调用,这在spring框架框架中应用也很多,通常是在bean实例化执行自己的一下初始化逻辑。
至此,BeanPostProcessor的实现原理分析结束。总结一下
2.3 总结
BeanPostProcessor及其子接口就是为了影响bean的实例化,初始化过程。在每个bean的加载流程中都会判定是否存在针对该bean类型的后置处理器,如果有执行处理程序。spring以及springboot的很多功能实现都是基于此,因此,理解BeanPostProcessor的原理对理解和使用spring框架非常重要。