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.
- postProcessBeforeInstantiation()--自定义对象-->postProcessAfterInitialization();
- postProcessBeforeInstantiation() -->postProcessAfterInstantiation-->postProcessBeforeInitialization()-->postProcessAfterInitialization()
我们看出:postProcessBeforeInstantiation一定执行, postProcessAfterInitialization一定执行.
至此:不知道读者是否体会到了InstantiationAwareBeanPostProcessor与BeanPostProcessor接口 以及其定义的4个方法的妙处.
四个方法执行的顺序对理解spring创建流程有着重要意义。
BeanPostProcessor 本身就是一种拦截的设计思想. 拦截的目的就是做额外的操作, 即 扩展。
欢迎大家关注我的公众号【源码行动】,最新个人理解及时奉送。

spring源码系列7:Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别的更多相关文章
- Spring源码系列 — BeanDefinition
一.前言 回顾 在Spring源码系列第二篇中介绍了Environment组件,后续又介绍Spring中Resource的抽象,但是对于上下文的启动过程详解并未继续.经过一个星期的准备,梳理了Spri ...
- 事件机制-Spring 源码系列(4)
事件机制-Spring 源码系列(4) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcess ...
- Ioc容器依赖注入-Spring 源码系列(2)
Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...
- Ioc容器BeanPostProcessor-Spring 源码系列(3)
Ioc容器BeanPostProcessor-Spring 源码系列(3) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Io ...
- AOP执行增强-Spring 源码系列(5)
AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...
- Ioc容器beanDefinition-Spring 源码系列(1)
Ioc容器beanDefinition-Spring 源码系列(1) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器 ...
- Spring源码系列 — 注解原理
前言 前文中主要介绍了Spring中处理BeanDefinition的扩展点,其中着重介绍BeanDefinitionParser方式的扩展.本篇文章承接该内容,详解Spring中如何利用BeanDe ...
- Spring源码系列 — BeanDefinition扩展点
前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition ...
- Spring源码系列 — Bean生命周期
前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...
- Spring源码系列(二)--bean组件的源码分析
简介 spring-bean 组件是 Spring IoC 的核心,我们可以使用它的 beanFactory 来获取所需的对象,对象的实例化.属性装配和初始化等都可以交给 spring 来管理. 本文 ...
随机推荐
- mysql中查询字段为null或者不为null的sql语句怎么写?
在mysql中,查询某字段为空时,切记不可用 = null,而是 is null,不为空则是 is not null select * from table where column is null; ...
- django配置静态文件的两种方法
方法一:按照django配置静态文件的方法,可以在APP应用目录下创建一个static的文件夹,然后在static文件夹下创建一个和APP同名的文件夹,如我有一个blog的django项目,在下面有一 ...
- 详细的App推广前的准备工作
App开发完成后,推广App自然就成为下一步工作的重点.兵马未动,粮草先行,这里为大家整理了一份App推广前需要准备一些事项,希望能给正在准备开展App推广的小伙伴们一些帮助. 众所周知,App推广的 ...
- 初学者-asp.net三层架构
一.概述: 通常意义上的三层架构就是将整个业务应用划分为:表现层(UI).业务逻辑层(BLL).数据访问层(DAL).区分层次的目的即为了“高内聚,低耦合”的思想.是一种总体设计的思想. 1.表现层( ...
- 整理总结 python 中时间日期类数据处理与类型转换(含 pandas)
我自学 python 编程并付诸实战,迄今三个月. pandas可能是我最高频使用的库,基于它的易学.实用,我也非常建议朋友们去尝试它.--尤其当你本身不是程序员,但多少跟表格或数据打点交道时,pan ...
- 网关鉴权后下游统一filter获取用户信息
1. 场景描述 最近有点忙,在弄微服务nacos+springcloud gateway这块工作,以前只是简单应用,这次因为要对接10几个系统或者平台,还的鉴权,等后续稍微闲点了,把这块东西总结下. ...
- setStyleSheet 设置背景图片
设置背景颜色很简单,大部分教程都对 设置背景图像有一个小坑. 设置背景图像主要有两种情况, 第一种:图片的绝对路径 ``` this->setObjectName("mainWindo ...
- mysql 5.7 Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column ...报错
使用mysql在执行一条插入语句时 , ', "hhh"); 报错:Expression #1 of ORDER BY clause is not in GROUP BY clau ...
- 多tomcat服务和nginx负载均衡配置
1.nginx服务安装及配置,详见:linux 配置之安装nginx 2.多个tomcat服务安装及配置,详见:linux 配置多个tomcat 3.关键配置nginx.conf文件 http { i ...
- Flask基础(02)-->搭建Flask项目虚拟环境
什么是虚拟环境? 虚拟环境:其实就是一个文件夹,是python环境的复制 为什么要搭建虚拟环境? 因为一台计算机上可能要同时开发多个不同的项目,那么这些项目有可能用到同一个包的不同版本,如此一来,我们 ...