什么是BeanPostProcessor
BeanPostProcessor从本质上讲也是一个bean,它的实例化在普通bean之前,然后作用于普通bean。BeanPostProcessor可以作用于普通bean生命周期的以下几个阶段:
- postProcessBeforeInitialization
- postProcessMergedBeanDefinition
- postProcessAfterInitialization
- postProcessPropertyValues
- postProcessBeforeInstantiation
- postProcessAfterInstantiation
BeanPostProcessor实例化时机及排序问题
AbstractApplicationContext#refresh
具体实例化BeanPostProcessor的方法为registerBeanPostProcessors,该方法中有很多重复代码,大体可以分为查找、排序、注册三个阶段。具体排序规则如下:
- 实现了 PriorityOrdered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 实现了 Ordered 且未实现 MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 未实现了 PriorityOrdered、Ordered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 实现了 PriorityOrdered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 实现了Ordered、MergedBeanDefinitionPostProcessor 接口的BeanPostProcessor
- 未实现了 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;
@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;
}
}
创建配置类AppConfig
package com.test.spring.config;
import org.springframework.context.annotation.ComponentScan;
/**
* 这里可以不用加@Configuration
* AnnotationConfigApplicationContext会将构造方法注入的类,解析成bd
*/
@ComponentScan("com.test.spring")
public class AppConfig {
}
创建一个BeanFactoryPostProcessor
@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) {
}
}
该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;
@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);
}
}
该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;
@Component
public 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;
@Component
public 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;
@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
4.BeanPostProcessor#postProcessBeforeInitialization
这个方法前后及其子类实现,一般都是一些钩子函数,简单罗列一下
- 方法之前
- AbstractAutowireCapableBeanFactory#invokeAwareMethods
- setBeanName
- setBeanClassLoader
- setBeanFactory
- AbstractAutowireCapableBeanFactory#invokeAwareMethods
- 子类实现
- InitDestroyAnnotationBeanPostProcessor$LifecycleElement
- @PostConstruct标注的方法
- ApplicationContextAwareProcessor#invokeAwareInterfaces
- setEnvironment
- setEmbeddedValueResolver
- setResourceLoader
- setApplicationEventPublisher
- setMessageSource
- setApplicationStartup
- setApplicationContext
- InitDestroyAnnotationBeanPostProcessor$LifecycleElement
- 方法之后
- AbstractAutowireCapableBeanFactory#invokeInitMethods
- 处理实现InitializingBean接口的bean
- AbstractAutowireCapableBeanFactory#invokeInitMethods
5.BeanPostProcessor#postProcessAfterInitialization
在这一阶段,最常见的作用就是动态代理。比如@EnableTransactionManagement注解会注入一个类型为 InfrastructureAdvisorAutoProxyCreator 的BeanPostProcessor,这个类的祖父类(AbstractAutoProxyCreator)的方法实现(postProcessAfterInitialization)就是对满足条件的bean进行动态代理。相关源码如下:
PS : @EnableAspectJAutoProxy注解和@EnableAsync注解注入的BeanPostProcessor,也会在这一阶段对满足条件的bean进行动态代理
总结
BeanPostProcessor的作用很强大,但是也很危险,如果不加条件判断要处理的特定bean,所有的bean的都会受影响,所有的bean的都会受影响,所有的bean的都会受影响,重要的事情说三遍。