InstantiationAwareBeanPostProcessor

一、InstantiationAwareBeanPostProcessor简述与demo示例

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();
    }
}
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){

            //利用cglib 其 生成动态代理
            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;
    }
}
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;
    }
}
<?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>
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 + '\'' +
                '}';
    }
}

运行结果如下:  由于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]

目标方法前:public java.lang.String com.nancy.ioc.Bean.toString()

目标方法后:public java.lang.String com.nancy.ioc.Bean.toString()

Bean{name='我修改啦'}

二、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;
  }

3、跟进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。

 

 

 

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值