目录
2.InstantiationAwareBeanPostProcessor
2.1postProcessBeforeInstantiation
2.2postProcessAfterInstantiation
3.SmartInstantiationAwareBeanPostProcessor
3.1determineCandidateConstructors()
4.MergedBeanDefinitionPostProcessor
5.DestructionAwareBeanPostProcessor
最近在写spring bean的生命周期的时候,发现无论如何都绕不开BeanPostProcessor后置处理器,这货有多强呢?bean的生命周期和九大处理器可有所耳闻?先简短描述一下bean生命周期,其实就是bean的实例化、属性赋值、初始化、销毁四大阶段,而这四大阶段里又穿插着九大后置处理器,如果单独记忆这九大后置处理器,那真的是<<JAVA从入门到放弃>>,可是归纳起来看,你就会发现这些处理器都是来自于同一个爸爸--BeanPostProcessor接口,而最重要的几个子接口分别是:
1、InstantiationAwareBeanPostProcessor
2、SmartInstantiationAwareBeanPostProcessor
3、MergedBeanDefinitionPostProcessor
4、DestructionAwareBeanPostProcessor
他有两个原生方法,分别在bean的初始化前后调用,方法如下
postProcessBeforeInitialization(Object bean, String beanName)
postProcessAfterInitialization(Object bean, String beanName)
下面开讲之前先给大家看一下文章结构
1.展示beanPostProcessor思维导图
2.分别讲解几个子类接口/子实现类的作用
3.注册时机
1. BeanPostProcessor思维导图
先上流程图
看不清可以来下面链接看
Spring生命周期思维导图| ProcessOn免费在线作图,在线流程图,在线思维导图
继承图如下:(至关重要!!!)
在图里可以发现,有两个子类继承了他的祖辈们的财产,分别是AutowiredAnnotationBeanPostProcessor和CommonAnnotationPostProcessos ,下面讲的那几个接口,很多时候都是靠他们两个实现类去实现的。
2.InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor有三个方法,而默认实现类是AbstractAutoProxyCreator
1. postProcessBeforeInstantiation() 在bean实例化前调用,也是第一次扩展后置处理器的调用时机。
2.postProcessAfterInstantiation()在bean实例化后、属性赋值前 调用,第五次扩展后置处理器的调用时机。
3. postProcessPropertyValues() @Autowired在这里进行DI,将获取的属性封装在 PropertyValues 的实例对象 pvs 中,在属性赋值阶段,第六次扩展后置处理器的调用时机
先直接上一段代码:
建一个Son类和Father类,son类继承father类
public class Father {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge( int age ) {
this.age = age;
}
@Override
public String toString() {
return "Father{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Son extends Father{
private String money;
public String getMoney() {
return money;
}
public void setMoney( String money ) {
this.money = money;
}
@Override
public String toString() {
return "Son{" +
"money='" + money + '\'' +
'}';
}
}
spring.xml
/**
* @Author 小源仔
* @Date 2023/5/9 21:10
* @description:
*/
public class BeanInstantiationDemo {
public static void main( String[] args ) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.addBeanPostProcessor( new MyInstantiationAwareBeanPostProcessor() );
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String location = "spring.xml";
Resource resource = new ClassPathResource(location);
//字符编码格式
EncodedResource encodedResource = new EncodedResource(resource,"UTF-8");
beanDefinitionReader.loadBeanDefinitions( encodedResource );
Son son = beanFactory.getBean("son",Son.class);
System.out.println(son);
// Father father = beanFactory.getBean( "father",Father.class );
// System.out.println(father);
}
static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
/**
* 实例化bean之前,相当于new这个bean之前
* 当调用postProcessBeforeInstantiation返回对象时,就可以直接返回对象了,就不会走到AbstractAutowireCapableBeanFactory的doCreateBean方法
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation,beanName="+beanName);
return null;
}
/**
* 实例化bean之后,相当于new这个bean之后
* 如果返回值是false,那么就不进行下面的依赖注入流程了
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
return true;
}
/**
* bean已经实例化完成,在属性注入时阶段触发,
* Instantiation(实例化)
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessProperties");
return null;
}
// /**
// * 这个方法在spring低版本中使用,在高版本已经过时了,使用postProcessProperties代替
// * deprecated as of 5.1, in favor of {@link #postProcessProperties(PropertyValues, Object, String)}
// * @param pvs
// * @param pds
// * @param bean
// * @param beanName
// * @return
// * @throws BeansException
// */
// @Override
// public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
// return null;
// }
/**
* 初始化bean之前,相当于把bean注入spring上下文之前
* Initialization(初始化)
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInitialization");
return bean;
}
/**
* 初始化bean之后,相当于把bean注入spring上下文之后
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessAfterInitialization");
return bean;
}
}
}
这个代码里面把所有方法都给实现了一遍,具体顺序自己看图里。
2.1postProcessBeforeInstantiation
这个方法因为是在对象实例化前调用,如果返回的是具体的对象,而不是null的话,这个返回值就会代替原来该生成的目标对象的实例,相当于偷梁换日了。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
举例子:
还是上面代码,稍微改一下:
public static void main( String[] args ) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
beanFactory.addBeanPostProcessor( new MyInstantiationAwareBeanPostProcessorV2() );
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
String location = "spring.xml";
Resource resource = new ClassPathResource(location);
//字符编码格式
EncodedResource encodedResource = new EncodedResource(resource,"UTF-8");
beanDefinitionReader.loadBeanDefinitions( encodedResource );
Son son = beanFactory.getBean("son",Son.class);
System.out.println(son);
// Father father = beanFactory.getBean( "father",Father.class );
// System.out.println(father);
}
static class MyInstantiationAwareBeanPostProcessorV2 implements InstantiationAwareBeanPostProcessor{
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if(ObjectUtils.nullSafeEquals("son",beanName) && Son.class.equals(beanClass)){
//把配置完成的 superUser bean覆盖
return new Father();
}
return null;//这里表示什么都不变化
}
}
debug进源码跟大家看一下:
因为流程比较多,所以我用文字来表达一下前面的流程:
1.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, Class<T> requiredType)
2.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
3.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd)
执行完核心方法后,正常返回的bean是null,可是因为我们前面让bean有返回值了,所以下面源码在继续debug的时候就能看到它返回一个father对象,替换了原先的son对象,成功“偷梁换日”
继续进入applyBeanPostProcessorsBeforeInstantiation()方法,这里就是循环实现了InstantiationAwareBeanPostProcessor的接口,其实就只有一个接口,那就是我们自定义的
然后继续进入postProcessBeforeInstantiation方法里
返回到上两步
因为bean生成了代理对象,所以会继续调用applyBeanPostProcessorsAfterInitialization,如果有实现了postProcessAfterInstantiation()这个方法,就会被直接执行。如果没有生成代理对象,这个方法将会在后面实例化对象后,则第五次扩展后置处理器,还会被调用到。
2.2postProcessAfterInstantiation
上面流程已经讲述了这个方法的作用,这里就不再多讲
2.3postProcessProperties
还记得我们最前面自定义的代码吗,现在默认beanPostProcessorsBeforeInitialization()方法返回是空值(否则走不到postProcessProperties这一步),然后重新执行一遍代码,我带大家看看他的调用流程
1.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, Class<T> requiredType)
2.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
3.AbstractAutowireCapableBeanFactory#doCreateBean(beanName, mbdToUse, args)
进入populateBean()方法,从这里可以看出是在属性赋值阶段执行这个后置处理器的
AutowiredAnnotationBeanPostProcessor 中的 postProcessProperties 方法
记住这里,下面会讲到!!!会首尾呼应!!!
postProcessProperties 方法就是把缓存中已经被解析的@Autowired、@value、@Resource的属性、方法拿出来,属性赋值进bean实例中
3.SmartInstantiationAwareBeanPostProcessor
有意思啊,这个smartInstantiationAwareBeanPostProcessor接口,居然是前面讲的InstantiationAwareBeanPostProcessor的儿子。不禁感慨真就上阵父子兵啊!
我们来看下他的两个方法:
1.determineCandidateConstructors() 选举出合适的构造函数对象(如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来)
2.getEarlyBeanReference() 解决循环依赖,提前暴露一个工厂,工厂是三级缓存
3.1determineCandidateConstructors()
继续上面的代码debug:
1.org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name, Class<T> requiredType)
2.AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
3.AbstractAutowireCapableBeanFactory#doCreateBean(beanName, mbdToUse, args)
createBeanInstance()核心逻辑是寻找合适的构造器,并实例化对象,下面进入createBeanInstance()方法
继续进入
一般我们不需要自定义接口去寻找他的构造器,他有实现类AutowiredAnnotationBeanPostProcessor,@AutoWired注解在构造器上时才会触发这个后置处理器的使用,这里就不继续讲他的实现类了。
3.2getEarlyBeanReference()
这个方法可有意思,spring大名鼎鼎的依赖注入就是在这里实现第一步的,他提前曝光了一个工厂对象,是一个三级缓存来的(singletonFactories),用于创建beanName所对应的Bean对象。这个bean是前面实例化后,还未到属性赋值阶段的
简单说一下spring三级缓存:
Map<String, Object> singletonObjects (一级缓存)
key:beanName,value:经历了spring完整生命周期的bean对象。
Map<String, Object> earlySingletonObjects(二级缓存)
key:beanName,value:不完整的单例对象,也就是还没有初始化完毕。
Map<String, ObjectFactory<?>> singletonFactories(三级缓存)
key:beanName,value:单例工厂,用于创建beanName所对应的Bean对象。
在AbstractAutowireCapableBeanFactory的doCreateBean()方法中,在对bean实例化以后填充属性之前(一般称为早期对象,还没被属性赋值),会将其放入第三级缓存。
addSingletonFactory:把我们的早期对象包装成一个singletonFactory,该对象提供了一个getObject方法,该方法内部调用的就是getEarlyBeanReference()方法
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
看下addSingletonFactory(),他就是把工厂对象给存了起来
进入getEarlyBeanReference()方法中:
AbstractAutoProxyCreator是SmartInstantiationAwareBeanPostProcessor的实现类之一,其重写了getEarlyBeanReference方法:
一看就是跟动态代理相关的
4.MergedBeanDefinitionPostProcessor
这个后置处理器只有CommonAnntationBeanPostProcessor和AutowiredAnnotationBeanPostProcessor两个实现类是有内容的,其他的都是空实现。他们两个的功能很类似,就是把实例化后的bean对象,解析它里面的@Resource 、@Autowired、@Value属性和方法,封装成InjectionMetadata类型,并放进缓存中,等属性赋值阶段时再从缓存中拿出数据来赋值
我们看一下AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors()方法
进入AutowiredAnnotationBeanPostProcessor的方法
CommonAnntationBeanPostProcessor也类似是这样,只不过是获取@Resource注解的属性/方法而已,这里就不赘述了。
还记得前面说的吗?封装成InjectionMetadata类型,并放进缓存中,等属性赋值阶段时再从缓存中拿出数据来赋值 我们也来看一下是怎么样获取到缓存数据的吧,我知道看到这里你可能不耐烦了,再忍忍,快结束了哈!
进入到AbstractAutowireCapableBeanFactory#populateBean(beanName, mbd, instanceWrapper)方法看一下
AutowiredAnnotationBeanPostProcessor 中的 postProcessProperties 方法
这里获取的缓存就是前面set进去的
有没有发现这里的图似曾相识,没错!就是文章一开始的InstantiationAwareBeanPostProcessor处理器的postProcessPropertyValues() 处理过程,哦豁,首尾呼应了呢!
5.DestructionAwareBeanPostProcessor
1.postProcessBeforeDestruction(Object bean, String beanName) Bean销毁之前的回调方法,
其典型实现有ApplicationListenerDetector用于处理ApplicationListener的添加和销毁、InitDestroyAnnotationBeanPostProcessor用于处理@PostConstruct和@PreDestroy、ScheduledAnnotationBeanPostProcessor用于处理@Scheduled注解。
2、requiresDestruction()判断是否需要进行销毁,一般情况下都是需要的
实现类
1、ApplicationListenerDetector 处理ApplicationListener的添加和销毁
2、InitDestroyAnnotationBeanPostProcessor 处理@PostConstruct和@PreDestroy
3、ScheduledAnnotationBeanPostProcessor 处理@Scheduled注解
6、原生实现类
这里讲一下重点的实现类ApplicationContextAwareProcessor
如果实现了里面的aware接口,就能获取到对应的能力
7、注册时机
1.AbstractApplicationContext#refresh()
2.AbstractApplicationContextegister#BeanPostProcessors(beanFactory);
3.PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
进入registerBeanPostProcessors()方法,代码如下:
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
// beanProcessorTargetCount表示BeanFactory中所有的BeanPostProcessor数量,+1表示BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
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);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
// 升序排序
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
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);
// Now, register all regular BeanPostProcessors.
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);
// Finally, re-register all internal BeanPostProcessors.
// MergedBeanDefinitionPostProcessor排在最后
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// ApplicationListenerDetector放在所有BeanPostProcessor之后,注意ApplicationListenerDetector的equals()方法实现
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
简单描述下:
1、该方法分别对实现了PriorityOrdered、Ordered和无顺序接口进行注册,而且MergedBeanDefinitionPostProcessor 接口还多添加了一次。
2、在代码的最后还添加了一个ApplicationListenerDetector()方法,用于获取容器中的ApplicationListener进行注册。
3、添加方法使用BeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor)。此时容器中已经保存的是BeanPostProcessor的实例,因为已经调用BeanFactory#getBean方法。
4、关于MergedBeanDefinitionPostProcessor接口,虽然通过internalPostProcessors重新添加了一次,但是并不会重复添加,因为addBeanPostProcessor方法是先remove,再add,这些BeanPostProcessor就会添加到最后。
最后:作为图灵学院一份子,学习来源于周瑜和徐庶两位我特别敬重的老师,站在巨人的肩膀上增加了自己的理解,本文不以商业化为目的,纯个人学习使用