spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

时间:2023-03-09 03:07:36
spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

更多文章点击--spring源码分析系列

主要分析内容:

一、InstantiationAwareBeanPostProcessor简述与demo示例

二、InstantiationAwareBeanPostProcessor与BeanPostProcessor对比

三、InstantiationAwareBeanPostProcessor源码分析:注册时机和触发点

(源码基于spring 5.1.3.RELEASE分析)

一、InstantiationAwareBeanPostProcessor简述与demo示例

spring源码分析系列 (3) spring拓展接口InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor继承自BeanPostProcessor 是spring非常重要的拓展接口,代表这bean的一段生命周期: 实例化(Instantiation)

 public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

     @Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
} default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
} @Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException { return null;
} @Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs;
} }

由于InstantiationAwareBeanPostProcessor继承自BeanPostProcessor, 其他接口可以参考spring源码分析系列 (2) spring拓展接口BeanPostProcessor,这里针对多出接口说明一下:

1、postProcessBeforeInstantiation调用时机为bean实例化(Instantiation)之前 如果返回了bean实例, 则会替代原来正常通过target bean生成的bean的流程. 典型的例如aop返回proxy对象. 此时bean的执行流程将会缩短, 只会执行

BeanPostProcessor#postProcessAfterInitialization接口完成初始化。

2、postProcessAfterInstantiation调用时机为bean实例化(Instantiation)之后和任何初始化(Initialization)之前。

3、postProcessProperties调用时机为postProcessAfterInstantiation执行之后并返回true, 返回的PropertyValues将作用于给定bean属性赋值. spring 5.1之后出现以替换@Deprecated标注的postProcessPropertyValues

4、postProcessPropertyValues已经被标注@Deprecated,后续将会被postProcessProperties取代。

示例demo:

 public class InstantiationAwareBeanPostProcessorTest {
private ApplicationContext applicationContext ; @Before
public void beforeApplicationContext(){
/**
* ApplicationContext 自动注册 BeanPostProcessor、InstantiationAwareBeanPostProcessor、BeanFactoryPostProcessor
* 不需要手动注册
* */
applicationContext = new ClassPathXmlApplicationContext("ioc-InstantiationAwareBeanPostProcessor.xml") ;
} @Test
public void test(){
Bean bean = applicationContext.getBean("bean", Bean.class) ;
System.out.println(bean);
} @After
public void after(){
((ClassPathXmlApplicationContext)applicationContext).close();
}
}

InstantiationAwareBeanPostProcessorTest.java

 public class LogicInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

     @Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessAfterInstantiation\n"); // 会影响postProcessProperties 是否执行,返回false不执行
return true;
} @Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessBeforeInstantiation\n");
if(beanClass == Bean.class){ //利用 其 生成动态代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(beanClass);
enhancer.setCallback(new BeanMethodInterceptor());
Bean bean = (Bean)enhancer.create();
System.out.print("返回动态代理\n");
return bean ;
}
return null ;
} @Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessProperties\n");
return pvs;
} //************************************** BeanPostProcessor ********************************************** @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessAfterInitialization\n");
return bean;
} @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessBeforeInitialization\n");
return bean;
}
}

LogicInstantiationAwareBeanPostProcessor.java

 public class BeanMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("目标方法前:" + method+"\n");
Object object = methodProxy.invokeSuper(o, objects);
System.out.println("目标方法后:" + method+"\n");
return object;
}
}

BeanMethodInterceptor.java

 <?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="bean" class="com.nancy.ioc.Bean">
<property name="name" value="zhouxiaoxing"/>
</bean> <bean id="logicInstantiationAwareBeanPostProcessor" class="com.nancy.ioc.InstantiationAwareBeanPostProcessor.LogicInstantiationAwareBeanPostProcessor"/> </beans>

ioc-InstantiationAwareBeanPostProcessor.xml

 public class Bean {
public Bean(){ }
public Bean(String name){
System.out.println("构造函数被调用啦");
this.name = name ;
} private String name ; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} @Override
public String toString() {
return "Bean{" +
"name='" + name + '\'' +
'}';
}
}

Bean.java

运行结果如下:  由于postProcessBeforeInstantiation通过cglib生成代理,  所以直接执行BeanPostProcessor#postProcessAfterInitialization接口完成初始化。bean生命周期缩短

beanName:bean执行..postProcessBeforeInstantiation
返回动态代理
beanName:bean执行..postProcessAfterInitialization
目标方法前:public java.lang.String com.nancy.ioc.Bean.toString() 目标方法后:public java.lang.String com.nancy.ioc.Bean.toString() Bean{name='null'}

修改LogicInstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation如下 :

     @Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessBeforeInstantiation\n");
return null ;
} @Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.print("beanName:"+beanName+"执行..postProcessProperties\n"); if(bean instanceof Bean){
//修改bean中name 的属性值
PropertyValue value = pvs.getPropertyValue("name");
System.out.print("修改之前 name 的value是:"+value.getValue()+"\n");
value.setConvertedValue("我修改啦");
return pvs;
}
return pvs;
}

运行结果如下:  由于postProcessBeforeInstantiation返回null 并 postProcessAfterInstantiation返回true 所以执行会postProcessProperties。此时bean生命周期正常process

beanName:bean执行..postProcessBeforeInstantiation
beanName:bean执行..postProcessAfterInstantiation
beanName:bean执行..postProcessProperties
修改之前 name 的value是:TypedStringValue: value [zhouxiaoxing], target type [null]
beanName:bean执行..postProcessBeforeInitialization
beanName:bean执行..postProcessAfterInitialization
Bean{name='我修改啦'}

详细demo示例可以参考: https://gitee.com/zhouxiaoxing91/learning-src/tree/master

二、InstantiationAwareBeanPostProcessor与BeanPostProcessor对比

1、BeanPostProcessor 执行时机为bean初始化(Initialization)阶段,日常可以拓展该接口对bean初始化进行定制化处理。

2、InstantiationAwareBeanPostProcessor 执行时机bean实例化(Instantiation)阶段,典型用于替换bean默认创建方式,例如aop通过拓展接口生成代理对应,主要用于基础框架层面。如果日常业务中需要拓展该,spring推荐使用适配器类InstantiationAwareBeanPostProcessorAdapter。

3、所有bean创建都会进行回调。

三、InstantiationAwareBeanPostProcessor源码分析:注册时机和触发点

1、由于InstantiationAwareBeanPostProcessor实质也是BeanPostProcessor接口,register时机是一致的,可参考:spring源码分析系列 (2) spring拓展接口BeanPostProcessor 。

2、这里着重分析接口触发的时机,跟BeanPostProcessor一样触发入口从AbstractAutowireCapableBeanFactory#createBean开始 :

   /**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* @see #doCreateBean
*/
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException { // 省略...... try {
/**
* postProcessorsBeforeInstantiation 触发入口
*/
// 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 {
/**
* postProcessAfterInstantiation、postProcessProperties 触发入口
*/
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
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);
}
}

2.1、跟进AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation, 分析postProcessorsBeforeInstantiation执行时机 :

   /**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@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) {
/**
* 回调beanPostProcessorsBeforeInstantiation实例化,如果返回bean非null则直接执行
* beanPostProcessorsAfterInitialization进行实例初始化
*/
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
} /**
* Apply InstantiationAwareBeanPostProcessors to the specified bean definition
* (by class and name), invoking their {@code postProcessBeforeInstantiation} methods.
* <p>Any returned object will be used as the bean instead of actually instantiating
* the target bean. A {@code null} return value from the post-processor will
* result in the target bean being instantiated.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to use instead of a default instance of the target bean, or {@code null}
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
*/
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
/**
* 只要其中一个postProcessBeforeInstantiation返回实例bean即结束回调,
* 这个bean将会直接返回给bean容器管理
*/
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
} @Override
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;
}

2、跟进AbstractAutowireCapableBeanFactory#doCreateBean, 分析postProcessAfterInstantiation、postProcessProperties 执行时机 :

  /**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* <p>Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException { // 省略...... // Initialize the bean instance.
Object exposedObject = bean;
try {
/** 依据bean definition 完成bean属性赋值 */
populateBean(beanName, mbd, instanceWrapper);
/** 执行bean初始化 */
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);
}
} // 省略...... return exposedObject;
}
跟进AbstractAutowireCapableBeanFactory#populateBean
 /**
* Populate the bean instance in the given BeanWrapper with the property values
* from the bean definition.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param bw the BeanWrapper with bean instance
*/
@SuppressWarnings("deprecation") // for postProcessPropertyValues
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
} // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
boolean continueWithPropertyPopulation = true; /**
* 满足两个要求:
* 1、BeanDefinition为应用程序bean,而非基础框架bean信息。
* 2、注册过InstantiationAwareBeanPostProcessor类型接口,上文有提到这个标志位。
* 3、注册了多个接口时,只要其中一个postProcessAfterInstantiation返回false,即停止后续执行。
*/
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
} /**
* 判定是否执行以下流程,受到postProcessAfterInstantiation返回结果影响
*/
if (!continueWithPropertyPopulation) {
return;
} PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); /**
* ioc依赖注入
*/
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
} /**
* InstantiationAwareBeanPostProcessor标志位 和 依赖注入检查标志位
*/
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
} /**
* 1、优先回调postProcessProperties. spring-5.1之后新增回调接口
* 2、再回调postProcessPropertyValues,一旦返回null即结束. spring-5.1之前逻辑
*/
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;
}
}
} /**
* 依赖注入校验
*/
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
} /**
* 此时会将上述处理后的PropertyValues应用于bean属性
*/
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
 

总结一下:

  • InstantiationAwareBeanPostProcessor的触发入口从AbstractAutowireCapableBeanFactory#createBean开始。
  • bean实例化之前会检测是否存在该类型的接口,并触发前置postProcessBeforeInstantiation。注册多个实例时会依次执行回调,任何一个返回非null则直接执行BeanPostProcessor#postProcessAfterInitialization完成初始化。返回的bean直接返回容器,生命周期缩短。
  • 后置postProcessAfterInstantiation会在实例化之后,依赖注入和初始化方法之前。注册多个接口只要其中一个返回false,即停止后续执行。 返回结果会影响后续执行流程,通过此定制化bean属性注入等操作。
  • 优先回调postProcessProperties,spring-5.1之后新增回调接口 用以替代标注过时的postProcessPropertyValues方法。
  • InstantiationAwareBeanPostProcessor设计主要给基础性框架使用,日常应用spring推荐使用适配器类InstantiationAwareBeanPostProcessorAdapter。