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);
<span class="hljs-keyword">if</span> (logger.isDebugEnabled()) {
	logger.debug(<span class="hljs-string">"Finished creating instance of bean '"</span> + beanName + <span class="hljs-string">"'"</span>);
}
<span class="hljs-keyword">return</span> beanInstance;

}

Object beanInstance = doCreateBean(beanName, mbdToUse, args);
<span class="hljs-keyword">if</span> (logger.isDebugEnabled()) {
	logger.debug(<span class="hljs-string">"Finished creating instance of bean '"</span> + beanName + <span class="hljs-string">"'"</span>);
}
<span class="hljs-keyword">return</span> 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.

postProcessBeforeInstantiation()–自定义对象–>postProcessAfterInitialization();
postProcessBeforeInstantiation() -->postProcessAfterInstantiation–>postProcessBeforeInitialization()–>postProcessAfterInitialization()
我们看出:postProcessBeforeInstantiation一定执行, postProcessAfterInitialization一定执行.

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

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

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值