在深入学习Spring Bean生命周期一节中,我们学习了Bean后置处理器BeanPostProcessor,用于在Bean初始化前后插入我们自己的逻辑(Bean增强,Bean代理等)。但是你知道BeanPostProcessor的子类InstantiationAwareBeanPostProcessor吗?他用于Bean实例化前后处理。
本节记录两者的区别以及简单原理分析。
Initialization为初始化的意思,Instantiation为实例化的意思。在Spring Bean生命周期中,实例化指的是创建Bean的过程,初始化指的是Bean创建后,对其属性进行赋值(populate bean)、后置处理等操作的过程,所以Instantiation执行时机先于Initialization。
先来看看BeanPostProcessor的类结构:
public interface BeanPostProcessor {// bean 初始化之前执行@Nullabledefault Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}// bean 初始化之后执行@Nullabledefault Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return bean;}
}
InstantiationAwareBeanPostProcessor为BeanPostProcessor的子类,新增了三个额外的方法:
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {&#64;Nullabledefault Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {return null;}default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;}&#64;Nullabledefault PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {return null;}/** 废弃 */&#64;Deprecated&#64;Nullabledefault PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;}
}
postProcessBeforeInitialization(Object bean, String beanName)
&#xff1a;bean&#xff1a;Bean实例&#xff1b;beanName&#xff1a;Bean名称。方法将在Bean实例的afterPropertiesSet方法或者自定义的init方法被调用前调用&#xff0c;此时Bean属性已经被赋值。方法返回原始Bean实例或者包装后的Bean实例&#xff0c;如果返回null&#xff0c;则后续的后置处理方法不再被调用。postProcessAfterInitialization(Object bean, String beanName)
&#xff1a;bean&#xff1a;Bean实例&#xff1b;beanName&#xff1a;Bean名称。方法将在Bean实例的afterPropertiesSet方法或者自定义的init方法被调用后调用&#xff0c;此时Bean属性已经被赋值。方法返回原始Bean实例或者包装后的Bean实例&#xff0c;如果返回null&#xff0c;则后续的后置处理方法不再被调用。postProcessBeforeInstantiation(Class> beanClass, String beanName)
&#xff1a;beanClass&#xff1a;待实例化的Bean类型&#xff1b;beanName&#xff1a;待实例化的Bean名称。方法作用为&#xff1a;在Bean实例化前调用该方法&#xff0c;返回值可以为代理后的Bean&#xff0c;以此代替Bean默认的实例化过程。返回值不为null时&#xff0c;后续只会调用BeanPostProcessor的 postProcessAfterInitialization方法&#xff0c;而不会调用别的后续后置处理方法&#xff08;如postProcessAfterInitialization、postProcessBeforeInstantiation等方法&#xff09;&#xff1b;返回值也可以为null&#xff0c;这时候Bean将按默认方式初始化。postProcessAfterInstantiation(Object bean, String beanName)
&#xff1a;bean&#xff1a;实例化后的Bean&#xff0c;此时属性还没有被赋值&#xff1b;beanName&#xff1a;Bean名称。方法作用为&#xff1a;当Bean通过构造器或者工厂方法被实例化后&#xff0c;当属性还未被赋值前&#xff0c;该方法会被调用&#xff0c;一般用于自定义属性赋值。方法返回值为布尔类型&#xff0c;返回true时&#xff0c;表示Bean属性需要被赋值&#xff1b;返回false表示跳过Bean属性赋值&#xff0c;并且InstantiationAwareBeanPostProcessor的postProcessProperties方法不会被调用。为了验证实例化和初始化的先后顺序&#xff0c;我们直接新建一个SpringBoot项目测试即可&#xff08;我这里还使用之前的老项目&#xff09;&#xff1a;
Spring入口类名称为SpringDemoApplication
。新建MyBeanPostProcessor
实现BeanPostProcessor接口&#xff1a;
public class MyBeanPostProcessor implements BeanPostProcessor {&#64;Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post processor before " &#43; beanName &#43; " initialization");}return bean;}&#64;Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post processor after " &#43; beanName &#43; " initialization");}return bean;}}
因为对所有的Bean生效&#xff0c;所以为了方便观察输出&#xff0c;这里仅当Bean名称为springDemoApplication
时才打印输出。
注册进容器中&#xff1a;
&#64;Bean
public MyBeanPostProcessor myBeanPostProcessor () {return new MyBeanPostProcessor();
}
接着新建MyBeanInstantiationPostProcessor
实现InstantiationAwareBeanPostProcessor接口&#xff1a;
public class MyBeanInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor {&#64;Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post process before " &#43; beanName &#43; " instantiation");}return null;}&#64;Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post process after " &#43; beanName &#43; " instantiation");}return true;}&#64;Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {if ("springDemoApplication".equals(beanName)) {System.out.println("post process " &#43; beanName &#43; " properties");}return pvs;}
}
记得配置到webconfig里面。
&#64;Bean
public MyBeanInstantiationPostProcessor myBeanInstantiationPostProcessor() {return new MyBeanInstantiationPostProcessor();
}
启动程序&#xff0c;输出如下所示&#xff1a;
如果将MyBeanInstantiationPostProcessor的postProcessAfterInstantiation方法返回值改为false&#xff0c;程序输出如下&#xff1a;
postProcessAfterInitialization和InstantiationAwareBeanPostProcessor的方法都和Bean生命周期有关&#xff0c;要分析它们的实现原理自然要从Bean的创建过程入手。Bean创建的入口为AbstractAutowireCapableBeanFactory
的createBean方法&#xff0c;查看其源码&#xff1a;
resolveBeforeInstantiation
方法给Bean后置处理器一个返回目标Bean实例代理的机会&#xff0c;所以我们先重点关注下这个方法的源码。
该方法先于下面的doCreateBean
方法&#xff0c;也就是说里面的操作逻辑实在Bean实例化之前完成的。
resolveBeforeInstantiation
方法源码如下所示&#xff1a;
相关注释直接标记在代码中&#xff0c;方便查看。
&#64;Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean &#61; null;//beforeInstantiationResolved默认属性值为false,表示Bean实例化前置操作未执行if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {//判断是否有InstantiationAwareBeanPostProcessors处理器if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType &#61; this.determineTargetType(beanName, mbd);//有的话执行PostProcessorsBeforeInstantiation方法if (targetType !&#61; null) {bean &#61; this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);//如果上述方法返回值不为null&#xff0c;则说明Bean已经在该方法中实例化了&#xff08;代理&#xff0c;增加&#xff09;&#xff0c;那么直接执行BeanPostProcessor的PostProcessorsAfterInitialization方法if (bean !&#61; null) {bean &#61; this.applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}//如果Bean不为null,则将beforeInstantiationResolved属性值设置truembd.beforeInstantiationResolved &#61; bean !&#61; null;}return bean;
}
上面方法返回的bean如果为空的话&#xff0c;AbstractAutowireCapableBeanFactory
的createBean方法将继续往下执行doCreateBean方法&#xff1a;
查看doCreateBean方法源码&#xff1a;
这个时候我们会发现这里源码很多&#xff0c;我们先不看其他部分&#xff08;Bean生命周期其他部分&#xff09;&#xff0c;重点关注populateBean和initializeBean方法。查看populateBean方法源码&#xff1a;
protected void populateBean(String beanName, RootBeanDefinition mbd, &#64;Nullable BeanWrapper bw) {if (bw &#61;&#61; null) {if (mbd.hasPropertyValues()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");}} else {if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {Iterator var4 &#61; this.getBeanPostProcessors().iterator();while(var4.hasNext()) {BeanPostProcessor bp &#61; (BeanPostProcessor)var4.next();if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp &#61; (InstantiationAwareBeanPostProcessor)bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {//这个地方需要注意&#xff0c;当返回值为false的时候&#xff0c;直接返回&#xff0c;后续赋值操作不执行了return;}}}}// begin 这一块为属性赋值&#xff0c;aotowired,通过类型或者名称注入PropertyValues pvs &#61; mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;int resolvedAutowireMode &#61; mbd.getResolvedAutowireMode();if (resolvedAutowireMode &#61;&#61; 1 || resolvedAutowireMode &#61;&#61; 2) {MutablePropertyValues newPvs &#61; new MutablePropertyValues((PropertyValues)pvs);if (resolvedAutowireMode &#61;&#61; 1) {this.autowireByName(beanName, mbd, bw, newPvs);}if (resolvedAutowireMode &#61;&#61; 2) {this.autowireByType(beanName, mbd, bw, newPvs);}pvs &#61; newPvs;}//end boolean hasInstAwareBpps &#61; this.hasInstantiationAwareBeanPostProcessors();boolean needsDepCheck &#61; mbd.getDependencyCheck() !&#61; 0;PropertyDescriptor[] filteredPds &#61; null;if (hasInstAwareBpps) {if (pvs &#61;&#61; null) {pvs &#61; mbd.getPropertyValues();}//属性赋值后&#xff0c;判断是否有InstantiationAwareBeanPostProcessor实例&#xff0c;有的话从缓存集合中获取遍历Iterator var9 &#61; this.getBeanPostProcessors().iterator();while(var9.hasNext()) {BeanPostProcessor bp &#61; (BeanPostProcessor)var9.next();if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp &#61; (InstantiationAwareBeanPostProcessor)bp;//逐个调用其postProcessProperties方法PropertyValues pvsToUse &#61; ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);if (pvsToUse &#61;&#61; null) {if (filteredPds &#61;&#61; null) {filteredPds &#61; this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}
//逐个调用其postProcessPropertyValues方法pvsToUse &#61; ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);if (pvsToUse &#61;&#61; null) {return;}}pvs &#61; pvsToUse;}}}if (needsDepCheck) {if (filteredPds &#61;&#61; null) {filteredPds &#61; this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);}if (pvs !&#61; null) {this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);}}
}
接着查看initializeBean方法源码&#xff1a;
protected Object initializeBean(String beanName, Object bean, &#64;Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() !&#61; null) {AccessController.doPrivileged(() -> {this.invokeAwareMethods(beanName, bean);return null;}, this.getAccessControlContext());} else {this.invokeAwareMethods(beanName, bean);}Object wrappedBean &#61; bean;if (mbd &#61;&#61; null || !mbd.isSynthetic()) {//执行PostProcessorsBeforeInitializationwrappedBean &#61; this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);}try {this.invokeInitMethods(beanName, wrappedBean, mbd);} catch (Throwable var6) {throw new BeanCreationException(mbd !&#61; null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);}if (mbd &#61;&#61; null || !mbd.isSynthetic()) {//执行PostProcessorsAfterInitializationwrappedBean &#61; this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}
至此我们通过查看Bean生命周期相关源码弄清楚了BeanPostProcessor和InstantiationAwareBeanPostProcessor相关方法的执行时机以及原理。
上面源码的追踪其实不仅涉及到了BeanPostProcessor和InstantiationAwareBeanPostProcessor相关方法的执行时机以及原理&#xff0c;更是整个Bean生命周期创建过程。
下面通过一张流程图总结本文&#xff1a;