• spring源码系列7:Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别


    概念

    Bean创建过程中的“实例化”与“初始化”名词

    • 实例化(Instantiation): 要生成对象, 对象还未生成.
    • 初始化(Initialization): 对象已经生成.,赋值操作。

    BeanPostProcessor :
    发生在 BeanDefiniton 加工Bean 阶段. 具有拦截器的含义. 可以拦截BeanDefinition创建Bean的过程, 然后插入拦截方法,做扩展工作.

    • postProcessBeforeInitialization初始化前置处理 (对象已经生成)
    • postProcessAfterInitialization初始化后置处理 (对象已经生成)

    InstantiationAwareBeanPostProcessor: 继承于BeanPostProcessor ,所以他也是一种参与BeanDefinition加工Bean过程的BeanPostProcessor拦截器, 并且丰富了BeanPostProcessor的拦截.

    • postProcessBeforeInstantiation 实例化前置处理 (对象未生成)
    • postProcessAfterInstantiation 实例化后置处理 (对象已经生成)
    • postProcessPropertyValues 修改属性值。(对象已经生成)

    总的来说:

    BeanPostProcessor定义的方法是在对象初始化过程中做处理。
    InstantiationAwareBeanPostProcessor定义的方法是在对象实例化过程中做处理

    发生时机

    1.postProcessBeforeInstantiation 调用时机
    BeanDefinition创建Bean的开端是在createBean()方法也就是流水线的开始处。

    	    @Override
    	protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    		...省略
    		try {
    			// 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);
    		}
    
    		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    		if (logger.isDebugEnabled()) {
    			logger.debug("Finished creating instance of bean '" + beanName + "'");
    		}
    		return beanInstance;
    	}
    

    看这段英文注释: Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.

    给BeanPostProcessor一个机会去返回一个代理对象. 就是在流水线doCreateBean()生成对象之前, 给用户自定义返回一个对象的机会.

    再看看resolveBeforeInstantiation(beanName, mbdToUse)是如何处理自定义返回对象的.

    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;
    	}
    
    • 判断是有有InstantiationAwareBeanPostProcessor的BeanPostProcessor
    • 有则调用的是InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()实例化前置处理方法,也就是在Bean没有生成之前执行。(注意:这里所说的是Bean未生成指的是Bean没有走spring定义创建Bean的流程,也就是doCreateBean()方法。)
    • 如果postProcessBeforeInstantiation()返回的对象不为空, 那么对象的生成阶段直接完成
    • 接着调用postProcessAfterInitialization()[初始化后置处理] 处理这个对象.
    • 如果为空?则走流水线doCreateBean()创建对象, 对象初始化.

    2.postProcessAfterInstantiation调用时机

    上文resolveBeforeInstantiation()没有返回bean.则走流水线创建Bean

    doCreateBean(beanName, mbdToUse, args)创建对象,会经过populateBean(beanName, mbd, instanceWrapper)方法。

    populateBean(beanName, mbd, instanceWrapper)依次执行postProcessAfterInstantiation() postProcessPropertyValues()

    3.postProcessBeforeInitialization调用时机

    doCreateBean(beanName, mbdToUse, args)创建对象,会经过initializeBean(beanName, exposedObject, mbd);方法。

    initializeBean(beanName, exposedObject, mbd); 会首先执行 postProcessBeforeInitialization()方法

    4.postProcessAfterInitialization

    initializeBean(beanName, exposedObject, mbd); 会首先执行 postProcessAfterInitialization()方法

    总结:

    实例化--->初始化

    • BeanPostProcessor定义的方法是在对象初始化过程中做处理。
    • InstantiationAwareBeanPostProcessor定义的方法是在对象实例化过程中做处理

    会形成两种执行流程完成BeanDefinition 创建Bean.

    1. postProcessBeforeInstantiation()--自定义对象-->postProcessAfterInitialization();
    2. postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessBeforeInitialization()-->postProcessAfterInitialization()

    我们看出:postProcessBeforeInstantiation一定执行, postProcessAfterInitialization一定执行.

    至此:不知道读者是否体会到了InstantiationAwareBeanPostProcessor与BeanPostProcessor接口 以及其定义的4个方法的妙处.

    四个方法执行的顺序对理解spring创建流程有着重要意义。

    BeanPostProcessor 本身就是一种拦截的设计思想. 拦截的目的就是做额外的操作, 即 扩展。

    欢迎大家关注我的公众号【源码行动】,最新个人理解及时奉送。
    在这里插入图片描述

  • 相关阅读:
    Java并发编程:并发容器之ConcurrentHashMap(转载)
    Java ConcurrentModificationException异常原因和解决方法
    Java并发编程:同步容器
    Java并发编程:深入剖析ThreadLocal
    错误:The POM for org.codehaus.plexus:plexus-compiler-api:jar:2.2 is invalid, transitive dependencies (if any) will not be available, enable debug logging for more details的解决方法
    maven工程中引入oracle驱动报错Missing artifact com.oracle:ojdbc14:jar:10.2.0.4.0
    部署时发出警告: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.jee.server:jx-web' did not find a matching property.的解决方法
    [WARNING] The POM for com.tao:jx-service:jar:0.0.1-SNAPSHOT is missing, no dependency information available
    maven工程中警告[WARNING] Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
    Eclipse中Errors occurred during the build最简单的解决方法
  • 原文地址:https://www.cnblogs.com/smallstudent/p/11724142.html
Copyright © 2020-2023  润新知