概念

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 本身就是一种拦截的设计思想. 拦截的目的就是做额外的操作, 即 扩展。

欢迎大家关注我的公众号【源码行动】,最新个人理解及时奉送。

spring源码系列7:Spring中的InstantiationAwareBeanPostProcessor和BeanPostProcessor的区别的更多相关文章

  1. Spring源码系列 — BeanDefinition

    一.前言 回顾 在Spring源码系列第二篇中介绍了Environment组件,后续又介绍Spring中Resource的抽象,但是对于上下文的启动过程详解并未继续.经过一个星期的准备,梳理了Spri ...

  2. 事件机制-Spring 源码系列(4)

    事件机制-Spring 源码系列(4) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProcess ...

  3. Ioc容器依赖注入-Spring 源码系列(2)

    Ioc容器依赖注入-Spring 源码系列(2) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostPr ...

  4. Ioc容器BeanPostProcessor-Spring 源码系列(3)

    Ioc容器BeanPostProcessor-Spring 源码系列(3) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Io ...

  5. AOP执行增强-Spring 源码系列(5)

    AOP增强实现-Spring 源码系列(5) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器BeanPostProc ...

  6. Ioc容器beanDefinition-Spring 源码系列(1)

    Ioc容器beanDefinition-Spring 源码系列(1) 目录: Ioc容器beanDefinition-Spring 源码(1) Ioc容器依赖注入-Spring 源码(2) Ioc容器 ...

  7. Spring源码系列 — 注解原理

    前言 前文中主要介绍了Spring中处理BeanDefinition的扩展点,其中着重介绍BeanDefinitionParser方式的扩展.本篇文章承接该内容,详解Spring中如何利用BeanDe ...

  8. Spring源码系列 — BeanDefinition扩展点

    前言 前文介绍了Spring Bean的生命周期,也算是XML IOC系列的完结.但是Spring的博大精深,还有很多盲点需要摸索.整合前面的系列文章,从Resource到BeanDefinition ...

  9. Spring源码系列 — Bean生命周期

    前言 上篇文章中介绍了Spring容器的扩展点,这个是在Bean的创建过程之前执行的逻辑.承接扩展点之后,就是Spring容器的另一个核心:Bean的生命周期过程.这个生命周期过程大致经历了一下的几个 ...

  10. Spring源码系列(二)--bean组件的源码分析

    简介 spring-bean 组件是 Spring IoC 的核心,我们可以使用它的 beanFactory 来获取所需的对象,对象的实例化.属性装配和初始化等都可以交给 spring 来管理. 本文 ...

随机推荐

  1. JAVA父类的静态方法能否被子类重写?

    静态: 在编译时所分配的内存会一直存在(不会被回收),直到程序退出内存才会释放这个空间,在实例化之前这个方法就已经存在于内存,跟类的对象没什么关系.子类中如果定义了相同名称的静态方法,并不会重写,而应 ...

  2. 任务分线程实现(java)

    1.创建一个类,用户存储信息 public class Users { private String userid; private String username; public Users() { ...

  3. master.TableNamespaceManager: Namespace table not found. Creating...

    1.错误描述: 出现上述这个错误的原因是我之前已经安装了Cloudera Manager中的CDH,其中添加了所有的服务,当然也包含HBase.然后重新安装的时候,就会出现如下错误: Failed t ...

  4. 定义一个Person类,其中包括:1.定义属性:姓名、年龄、民族作为成员变量。定义静态成员变量:人数2.定义构造方法:对成员变量进行初始化。3.定义多个方法:分别显示相应的属性值,例如getName(){System.out.print("名称="+name+";"); }4.定义一个方法“成长”:实现年龄的增加,每执行一次年龄增加1

    题目显示不全,完整题目描述: (1)定义一个Person类,其中包括:1.定义属性:姓名:年龄:民族作为成员变量.定义静态成员变量:人数2.定义构造方法:对成员变量进行初始化.3.定义多个方法:分别显 ...

  5. pip安装路径

    pip show 模块名称 即可查看pip安装的包所在路径. 如numpy: pip show numpy

  6. abp(net core)+easyui+efcore实现仓储管理系统——EasyUI之货物管理一 (十九)

    abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统——ABP总体介绍(一) abp(net core)+ ...

  7. Python turtle库绘制简单图形

    一.简介 Python中的turtle库是一个直观有趣的图形绘制函数库.turtle库绘制图形有一个基本框架:一个小海龟在坐标系中爬行,其爬行轨迹形成了绘制图形. 二.简单的图形列举 1.绘制4个不同 ...

  8. Windows server 2008 快速搭建域环境

    之前根据网上的教程搭建,然后出现了很多问题,最后摸索出了一个比较稳妥一点的方法. 对于选系统这里,虽然上一篇文章已经说过了,这里也再强调一下,我使用的是08的系统,使用其他系统的暂不做评价,使用08系 ...

  9. 品Spring:SpringBoot轻松取胜bean定义注册的“第一阶段”

    上一篇文章强调了bean定义注册占Spring应用的半壁江山.而且详细介绍了两个重量级的注册bean定义的类. 今天就以SpringBoot为例,来看看整个SpringBoot应用的bean定义是如何 ...

  10. 关于react-router最新版本的使用

    现在react-router已经更新到了5.1.1版本,在一些使用方法上较之前有了很多改变,现做初步列举,以后会陆续更新. 关于引入react-router和基本使用 旧版本中引入react-rout ...