前言:在前几篇查漏补缺中,其实我们已经涉及到bean生命周期了,本篇内容进行详细分析。


首先看bean实例化过程:

分析:

bean实例化开始后

  • 注入对象属性后(前面IOC初始化十几篇文章)。
  • 检查激活Aware接口。
  • 执行BeanPostProcessor前置处理
  • 实例化bean,这里会检查InitializingBean和init-method方法。
  • 执行BeanPostProcessor后置处理
  • 注册销毁bean的回调方法(并不是必须)。
  • 使用bean。
  • 检查DisposableBean和destroy-method方法。

注意:Spring是不会主动去调用销毁方法,必须我们主动告知Spring容器。

示例

 public class BeanLifeCycle implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {

     private String msg;

     public BeanLifeCycle() {
System.out.println("调用构造函数:BeanLifeCycle()");
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
System.out.println("属性注入:setMsg");
this.msg = msg;
} @Override
public void setBeanName(String name) {
System.out.println("BeanNameAware#setBeanName 被调用");
} @Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("BeanClassLoaderAware#setBeanClassLoader 被调用");
} @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactoryAware#setBeanFactory 被调用"); } @Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean#afterPropertiesSet 被调用,并对msg属性进行修改");
this.msg = "InitializingBean#afterPropertiesSet方法对msg属性进行修改";
} @Override
public void destroy() throws Exception {
System.out.println("DisposableBean#destroy 被调用");
} public void initMethod() {
System.out.println("init-method 被调用,并对msg属性进行修改,调用顺序在InitializingBean之后");
this.msg = "init-method方法对msg属性进行修改";
} public void destroyMethod() {
System.out.println("destroy-method 被调用,调用顺序在DisposableBean之后");
}
}

上述为主测试类,另外为了测试BeanPostProcessor,我们还需增加如下测试类:

 public class BeanLifeCycleBeanPostProcessor implements BeanPostProcessor {

     @Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("beanName=" + beanName + " 初始化之前调用:BeanPostProcessor#postProcessBeforeInitialization!!!!!");
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("beanName=" + beanName + " 初始化之后调用:BeanPostProcessor#postProcessAfterInitialization!!!!!");
return bean;
}
}

具体配置如下:

 <bean id="beanLifeCycle" class="com.dev.basebean.lifecycle.BeanLifeCycle"
init-method="initMethod" destroy-method="destroyMethod" p:msg="属性注入"/>
<bean id="beanLifeCycleBeanPostProcessor" class="com.dev.basebean.lifecycle.BeanLifeCycleBeanPostProcessor"/>

测试代码:

     @Test
public void beanLifeCycleTest() {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:com/dev/config/lifecycle/lifecycle.xml");
BeanLifeCycle beanLifeCycle = context.getBean(BeanLifeCycle.class);
System.out.println("msg=" + beanLifeCycle.getMsg());
((ClassPathXmlApplicationContext) context).close();
}

运行结果如下:

通过以上运行结果,我们可知Bean的生命周期,总结如下:

  1. Spring容器根据实例化策略对Bean进行实例化(调用其构造方法)。
  2. 实例化完成后,如果该bean设置了一些属性,则利用set方法进行属性设置。
  3. 如果该bean实现了BeanNameAware接口,则调用其setBeanName方法。
  4. 如果该bean实现了BeanClassLoaderAware接口,则调用其setBeanClassLoader方法。
  5. 如果该bean实现了BeanFactoryAware接口,则调用其setBeanFactory方法。
  6. 如果容器中注册了BeanPostProcessor,则会调用其postProcessBeforeInitialization方法,完成bean前置处理。
  7. 如果该bean实现了InitializingBean接口,则调用其afterPropertiesSet方法。
  8. 如果该bean配置了init-method方法,则调用其指定的方法。
  9. 初始化完成后,如果容器中注册了BeanPostProcessor,则会调用其postProcessAfterInitialization方法,完成bean后置处理。
  10. 对象初始化完成,就可以使用bean了(对其进行各种骚操作,上述示例中调用了getMsg方法)。
  11. 在容器关闭之前,如果该bean实现了DisposableBean接口,则调用其destroy方法。
  12. 在容器关闭之前,如果该bean配置了destroy-method方法,则调用其指定方法。

至此bean的生命周期结束,该bean完成了其伟大的一生。


by Shawn Chen,2019.05.05,下午。

【spring源码分析】IOC容器初始化——查漏补缺(四)的更多相关文章

  1. 【spring源码分析】IOC容器初始化——查漏补缺(一)

    前言:在[spring源码分析]IOC容器初始化(十一)中提到了初始化bean的三个步骤: 激活Aware方法. 后置处理器应用(before/after). 激活自定义的init方法. 这里我们就来 ...

  2. 【spring源码分析】IOC容器初始化——查漏补缺(五)

    前言:我们知道在Spring中经常使用配置文件的形式对进行属性的赋值,那配置文件的值是怎么赋值到属性上的呢,本文将对其进行分析. 首先了解一个类:PropertySourcesPlaceholderC ...

  3. 【spring源码分析】IOC容器初始化——查漏补缺(二)

    前言:在[spring源码分析]IOC容器初始化(八)中多次提到了前置处理与后置处理,本篇文章针对此问题进行分析.Spring对前置处理或后置处理主要通过BeanPostProcessor进行实现. ...

  4. SPRING源码分析:IOC容器

    在Spring中,最基本的IOC容器接口是BeanFactory - 这个接口为具体的IOC容器的实现作了最基本的功能规定 - 不管怎么着,作为IOC容器,这些接口你必须要满足应用程序的最基本要求: ...

  5. 【spring源码分析】IOC容器初始化——查漏补缺(三)

    前言:本文分析InitializingBean和init-method方法,其实该知识点在AbstractAutowireCapableBeanFactory#initializeBean方法中有所提 ...

  6. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  7. spring源码分析---IOC(1)

    我们都知道spring有2个最重要的概念,IOC(控制反转)和AOP(依赖注入).今天我就分享一下spring源码的IOC. IOC的定义:直观的来说,就是由spring来负责控制对象的生命周期和对象 ...

  8. spring 源码之 ioc 容器的初始化和注入简图

    IoC最核心就是两个过程:IoC容器初始化和IoC依赖注入,下面通过简单的图示来表述其中的关键过程:

  9. Spring源码阅读-IoC容器解析

    目录 Spring IoC容器 ApplicationContext设计解析 BeanFactory ListableBeanFactory HierarchicalBeanFactory Messa ...

随机推荐

  1. 基于【 centos7】二 || 系统时间与网络时间同步

    # date // 查看系统时间 #hwclock // 查看硬件时间 # yum -y install ntp ntpdate 安装ntpdate工具 # ntpdate cn.pool.ntp.o ...

  2. [Vuex系列] - Mutation的具体用法

    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation.Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 ...

  3. 解决wpscan无法更新

    如果wpscan无法更新的话 一般的原因都是源或者更新地址无法访问 下面解决 updatedb #先更新一下系统的索引 locate wpscan #定位到wpscan的目录 大概就是updater. ...

  4. vagrant 搭建开发环境

    虚拟机盒子地址 https://app.vagrantup.com/boxes/search vagrant init hirocom/centos7.2vagrant up 修改配置 config. ...

  5. 解决PHP 7编译安装错误:cannot stat ‘phar.phar’: No such file or directory

    最近因为工作需要要使用PHP 7,所以从网上找教程进行安装, 结果编译没问题, 安装的时候报了错误. 错误如下 1 2 3 cp -pR -f phar.phar /usr/local/php7/bi ...

  6. Computer Vision_18_Image Stitching:A survey on image mosaicing techniques——2013

    此部分是计算机视觉部分,主要侧重在底层特征提取,视频分析,跟踪,目标检测和识别方面等方面.对于自己不太熟悉的领域比如摄像机标定和立体视觉,仅仅列出上google上引用次数比较多的文献.有一些刚刚出版的 ...

  7. 《浏览器工作原理与实践》<09>块级作用域:var缺陷以及为什么要引入let和const?

    在前面我们已经讲解了 JavaScript 中变量提升的相关内容,正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷 ...

  8. JAVA Calendar类获取上个月的第一天和最后一天

    原文:https://www.cnblogs.com/QQParadise/articles/4936313.html 获取上个月第一天的方法: Calendar calendar = Calenda ...

  9. 编码、加密、Hash

    今天没有编码,还是属于纯理论的东东,概念也比较多,但是实际真正完全理解它们的人不多,也很重要,这些东东在实际中也经常被用到,但需要真正理解了才能正确的使用它们,这里列一下相关司:MD5.SHA1.RS ...

  10. 开启树莓派自带的VNC功能

    前期准备 树莓派可以连接路由器或连上wifi,我用的是自己的小米路由器,目的是为了获取内网IP 工具准备 下载 vnc viewer https://www.realvnc.com/en/connec ...