攀登Spring珠穆朗玛峰:前置与后置处理器-爱代码爱编程
文章目录
- Spring的前置与后置处理器
- 前提知识
- 前置与后置处理器定义
- 前置处理器:BeanFactoryPostProcessor
- 后置处理器:BeanPostProcessor
- 1、InstantiationAwareBeanPostProcessor
- 2、SmartInstantiationAwareBeanPostProcessor
- 3、MergedBeanDefinitionPostProcessor
- 4、SmartInstantiationAwareBeanPostProcessor
- 5、InstantiationAwareBeanPostProcessor
- 6、InstantiationAwareBeanPostProcessor
- 7、InstantiationAwareBeanPostProcessor
- 8、InstantiationAwareBeanPostProcessor
- 9、DestructionAwareBeanPostProcessor
Spring的前置与后置处理器
在提及Spring的时候,很多地方总是会提到前置与后置处理器,本文将对这两种处理器做一下简单的介绍。
前提知识
以Java Config
的启动而言,Spring整体的流程大概可以分成两个阶段:解析与实例化
- 解析:加载各类配置资源并解析配置类的各种注解,最终封装成
BeanDefinition
,并添加到Spring的BeanDefinitionMap
中; - 实例化:Spring对这个阶段的处理,是将初始化和初始化分开的。根据
BeanDefinition
先实例化出Bean
对象,再填充对象的各个属性以完成对象完整的初始化,期间可能会发生循环依赖,并且还会在实例化这个阶段多次调用后置处理器。也会进行生命周期的回调。
前置与后置处理器定义
- 前置处理器:
BeanFactoryPostProcessor
- 后置处理器:
BeanPostProcessor
开发者通过实现这两个接口,并通过某种方式注入到Spring内,就可以参与Spring的初始化过程,在其中的某些阶段进行一些定制内容的增加。
这里的前置与后置是相对于Bean的实例化而言的。
前置处理器:BeanFactoryPostProcessor
在Bean对象实例化前,Spring会调用BeanFactoryPostProcessor
接口的postProcessBeanFactory
。
在这个阶段,spring刚刚完成了所有配置类的解析,完整的将所有的配置类转换成了对应的BeanDefinition
。但是尚且没有完成Bean
的实例化。在这个阶段,程序员可以对这些BeanDefiniton
进行二次修改。
postProcessBeanFactory
调用
public static void invokeBeanFactoryPostProcessors(
...
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
...
}
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
在refresh
的invokeBeanFactoryPostProcessors
里面,通过委托给PostProcessorRegistrationDelegate
,最终会进入到上面的方法,在这个方法里面会进行前置处理器的调用。
如果需要更早的调用前置处理器,可以通过实现PriorityOrdered
或Ordered
接口并指定优先级,spring在调用前置处理器的时候,是分类按优先级调用的。
- 先调用实现
PriorityOrdered
的BeanFactoryPostProcessor
,其内优先级越高的越早被调用; - 在调用实现
Ordered
的BeanFactoryPostProcessor
,其内优先级越高的越早被调用; - 最后调用没有实现上面两个接口的
BeanFactoryPostProcessor
;
Spring提供了一些可能会被使用的前置处理器
CustomScopeConfigurer
:可以用来注册自定义Scope(s)
;PropertyPlaceholderConfigurer
:可以用来读取配置文件中的键值对,替换BeanDefinition
中属性的占位符,比如xml文件中经常使用${jdbc.url}
,原理就是通过这个前置处理器实现的;PropertyOverrideConfigurer
:可以对BeanDefinition
定义的信息进行覆盖;
后置处理器:BeanPostProcessor
在Bean
的初始化期间调用,会在各个阶段调用很多次。
简单总结一下调用位置。
1、InstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation
方法:反射创建Bean前被调用
这个地方的调用很重要,postProcessBeforeInstantiation
后面还会被调用一次,但是和此处的作用是不一样的。
此处调用postProcessBeforeInstantiation
如果返回的值不为null:
- 直接使用该对象完成当前Bean的初始化(这种情况下,就会再调用
postProcessAfterInitialization
)。
也就是说我们就可以在这里地方决定要不要执行之后的Spring初始化流程。
调用栈
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
try {
// 调用后置处理器:初始化Bean之前,InstantiationAwareBeanPostProcessor,
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);
}
...
}
@Nullable
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;
}
@Nullable
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;
}
2、SmartInstantiationAwareBeanPostProcessor
determineCandidateConstructors
方法:推断构造函数
主要是为了完成Bean
对象构造方法的推断,用来反射创建对象
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//实例化对象(仅仅是生成对象,并非添加到spring单例池中,即目前并没有成为Spring Bean),
//调用 后置处理器 determineConstructorsFromBeanPostProcessors
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
...
}
在createBeanInstance
里面调用determineConstructorsFromBeanPostProcessors
@Nullable
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
return ctors;
}
}
}
}
return null;
}
3、MergedBeanDefinitionPostProcessor
postProcessMergedBeanDefinition
方法:合并BeanDefinition后
doCreateBean
调用方法:postProcessMergedBeanDefinition
这个阶段处于MergedBeanDefinition
刚刚解析完毕的时候,用来可以进行一些后处理。比如可以在对 bean 的实际实例进行后处理之前准备一些缓存的元数据。
Spring是通过BeanDefinition
来初始化对象的,但是在使用BeanDefinition
前,需要先进行BeanDefinition
的合并。
BeanDefinition
可指定父BeanDefinition
,子BeanDefinition
可继承父BeanDefinition
的属性。所以需要合并后的BeanDefinition
来实例化Bean。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
//调用后置处理器 MergedBeanDefinitionPostProcessors
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
...
}
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
4、SmartInstantiationAwareBeanPostProcessor
getEarlyBeanReference
方法:三级缓存来获取早期对象
这个阶段是将当前创建的对象放到三级缓存内,暂时不会被调用。当出现循环依赖的时候,便需要获取三级缓存,此时会调用getEarlyBeanReference
来获取早期引用。而在getEarlyBeanReference
就调用了后置处理器的getEarlyBeanReference
。
此时相当于定义了获取代理对象的方法(后置处理器),但暂时不会调用该后置处理器。
只有在出现循环依赖的时候会执行该后置处理器的处理操作。
-
出现循环依赖时,需要提前获取对象,所以
getEarlyBeanReference
方法里,通常是来生成代理来支持AOP。 -
如果当前初始化的
Bean
没有出现循环依赖,那么这个后置处理器便不会被调用。而AOP的处理会在其他地方进行。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
...
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");
}
//(是在 getEarlyBeanReference 里面调用的后置处理器 此时此时假如到了三级缓存里面,实际上还没有调用)
//调用后置处理器,SmartInstantiationAwareBeanPostProcessor 判断是否需要AOP,
//提前暴露出来,用来解析循环引用,做AOP
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
...
}
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
5、InstantiationAwareBeanPostProcessor
postProcessAfterInstantiation
方法:实例化Bean后,属性填充前
属性填充:populateBean
里面会进行两次后置处理器的调用。
这个方法处于的阶段在Bean
刚刚反射创建出来,但是还没有进行属性填充时。
这个方法的返回值可以决定当前类是否可以作为其他类的属性被注入。默认true
。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
...
Object exposedObject = bean;
try {
//填充属性(即自动注入) 完成第五次和第六次后置处理器的调用
// InstantiationAwareBeanPostProcessor.after
// hasInstantiationAwareBeanPostProcessors
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);
}
}
...
}
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
//在设置属性之前,让任何 InstantiationAwareBeanPostProcessors 有机会修改 bean 的状态。例如,这可用于支持字段注入样式。
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
...
}
6、InstantiationAwareBeanPostProcessor
postProcessProperties
方法:完成属性填充
比如用来支持@Resource
和@Autowired
的两个后置处理器都实现了这个方法。两个后置处理器都实现了不同的属性填充逻辑。
对于开发者而言,可以实现该方法,进而在这个阶段拦截和修改属性。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//属性填充
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
...
}
7、InstantiationAwareBeanPostProcessor
postProcessBeforeInstantiation
方法:完全初始化Bean前
注意区别第一次的后置处理器调用,和第一次调用的是同一个方法。
在这个阶段Spring借由各个后置处理器完成了以下几件事情:
InitDestroyAnnotationBeanPostProcessor
:@PostConstruct
的解析ImportAwareBeanPostProcessor
:ImportAware的setImportMetadata
方法调用ApplicationContextAwareProcessor
:各种Aware接口的方法调用
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
...
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 第七次调用后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
...
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
8、InstantiationAwareBeanPostProcessor
postProcessAfterInitialization
方法:初始化Bean阶段的最后时期
正常初始化对象时,会在这里进行AOP的处理,进行代理操作。
可以查看AbstractAutoProxyCreator
对该方法的重写
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
...
if (mbd == null || !mbd.isSynthetic()) {
//第八次调用后置处理器,处理器AOP,生成代理对象
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
...
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
9、DestructionAwareBeanPostProcessor
requiresDestruction
方法:销毁方法
当前初始化类如果实现了DisposableBean
,会注册该方法。
在Spring停止的时候,会调用所有的销毁方法。
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
...
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
}