Spring Bean的生命周期

Spring容器既Application或者WebApplication会在管理Bean的时候;为了尽可能的把自己内部的东西机制暴露出来给用户使用,所以在Bean创建的过程中加了很多机制,通过所谓的"处理器"Processor暴露出来,然后处理器都有自己的顺序,我们需要做的就是定义好处理器的逻辑,然后注册到Sprinhg容器中,Spring就会调用了。下面就是Spring管理Bean的生命周期图。

下面这张图描述的更为详细。

相关接口的分类

对于上面图看不懂不要着急因为你并不认识与生命周期相关的接口。Spring生命周期你可以理解为四个等级;每个等级中都用有相应的接口,实现其中某个接口或者将实现类注入到Sprng容器,容器就会在相应的时机调用其方法。详细信息可看下面的一个表格。

  • 工厂后处理器接口方法
  • 容器级生命周期接口方法
  • Bean级生命周期接口方法
  • Bean本身方法
分类 接口 调用时间
工厂后处理器接口 BeanFactoryPostProcessor 容器创建完毕,装配Bean源后立即调用
容器后处理器接口 InstantiationAwareBeanPostProcessor 分别在调用构造之前,注入属性之前,实例化完成时调用
容器后处理器接口 BeanPostProcessor 分别在Bean的初始化方法调用前后执行
Bean级后置处理器接口 BeanNameAware 注入属性后调用
Bean级后置处理器接口 BeanFactoryAware 注入属性后调用
Bean级后置处理器接口 InitializingBean 在类本身的初始化方法之前调用其方法(本身也是初始化方法)
Bean级后置处理器接口 DiposableBean 在类本身的销毁方法执行之前调用其方法(本身也是销毁方法)
Bean本身方法 init方法 在注入属性之后调用初始化方法
Bean本身方法 destroy方法 在关闭容器的时候进行销毁

测试SpringBean生命周期的Demo程序

本测试程序来自https://www.cnblogs.com/zrtqsk/p/3735273.html 我在这里说一下测试程序是如何测试SpringBean的生命周期的。首先将一个工厂后处理器 BeanFactoryPostProcessor接口实现注入容器,再将容器后处理器InstantiationAwareBeanPostProcessorBeanPostProcessor注入容器,又在自定义Person实现了Bean级后处理器BeanNameAwareBeanFactoryAwareInitializingBeanDiposableBean接口的相关方法,最后就是在自定义的Person类中实现了其本身的init()方法和destroy()方法。

  • 自定义Person类
public class Person implements BeanFactoryAware, BeanNameAware,
InitializingBean, DisposableBean { private String name;
private String address;
private int phone; private BeanFactory beanFactory;
private String beanName; public Person() {
System.out.println("【构造器】调用Person的构造器实例化");
} public String getName() {
return name;
} public void setName(String name) {
System.out.println("【注入属性】注入属性name");
this.name = name;
} public String getAddress() {
return address;
} public void setAddress(String address) {
System.out.println("【注入属性】注入属性address");
this.address = address;
} public int getPhone() {
return phone;
} public void setPhone(int phone) {
System.out.println("【注入属性】注入属性phone");
this.phone = phone;
} @Override
public String toString() {
return "Person [address=" + address + ", name=" + name + ", phone="
+ phone + "]";
} // 这是BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
System.out
.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");
this.beanFactory = arg0;
} // 这是BeanNameAware接口方法
@Override
public void setBeanName(String arg0) {
System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");
this.beanName = arg0;
} // 这是InitializingBean接口方法
@Override
public void afterPropertiesSet() throws Exception {
System.out
.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");
} // 这是DiposibleBean接口方法
@Override
public void destroy() throws Exception {
System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");
} // 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");
} // 通过<bean>的destroy-method属性指定的初始化方法
public void myDestory() {
System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");
}
}
  • MyBeanPostProcessor (实现容器级别后置处理器)
public class MyBeanPostProcessor implements BeanPostProcessor {
public MyBeanPostProcessor() {
super();
System.out.println("这是BeanPostProcessor实现类构造器!!");
// TODO Auto-generated constructor stub
} @Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");
return arg0;
} @Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
System.out
.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");
return arg0;
}
}
  • MyInstantiationAwareBeanPostProcessor(实现容器级别后置处理器)
public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
public MyInstantiationAwareBeanPostProcessor() {
super();
System.out
.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");
} // 接口方法、实例化Bean之前调用
@Override
public Object postProcessBeforeInstantiation(Class beanClass,
String beanName) throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");
return null;
} // 接口方法、实例化Bean之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");
return bean;
} // 接口方法、设置某个属性时调用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs,
PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
System.out
.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");
return pvs;
}
}
  • MyBeanFactoryPostProcessor (实现容器级别后置处理器)
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public MyBeanFactoryPostProcessor() {
super();
System.out.println("这是BeanFactoryPostProcessor实现类构造器!!");
} @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory arg0)
throws BeansException {
System.out
.println("BeanFactoryPostProcessor调用postProcessBeanFactory方法");
BeanDefinition bd = arg0.getBeanDefinition("person");
bd.getPropertyValues().addPropertyValue("phone", "110");
}
}
  • 配置Spring的xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"> <bean id="beanPostProcessor" class="com.jimisun.learnspringboot.web.MyBeanPostProcessor">
</bean> <bean id="instantiationAwareBeanPostProcessor"
class="com.jimisun.learnspringboot.web.MyInstantiationAwareBeanPostProcessor">
</bean> <bean id="beanFactoryPostProcessor" class="com.jimisun.learnspringboot.web.MyBeanFactoryPostProcessor">
</bean> <bean id="person" class="com.jimisun.learnspringboot.web.Person" init-method="myInit"
destroy-method="myDestory" scope="singleton" p:name="张三" p:address="广州"
p:phone="15900000000"/> </beans>
  • Main方法执行测试
public class Main {
public static void main(String[] args) { System.out.println("现在开始初始化容器"); ApplicationContext factory = new ClassPathXmlApplicationContext("bens.xml");
System.out.println("容器初始化成功");
//得到Preson,并使用
Person person = factory.getBean("person",Person.class);
System.out.println(person); System.out.println("现在开始关闭容器!");
((ClassPathXmlApplicationContext)factory).registerShutdownHook();
} }
  • 测试结果(我对Main方法执行结果做了格式化,方便参照)

LOGGER测试:现在开始初始化容器
【工厂构造】这是BeanFactoryPostProcessor实现类构造器!!
【工厂方法】BeanFactoryPostProcessor调用postProcessBeanFactory方法
【容器构造】这是BeanPostProcessor实现类构造器!!
【容器构造】这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!
【容器方法】InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法
【类构造】调用Person的构造器实例化
【容器方法】InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法
【类注入属性】注入属性address
【类注入属性】注入属性name
【类注入属性】注入属性phone
【Bean方法:BeanNameAware接口】调用BeanNameAware.setBeanName()
【Bean方法:BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()
【容器方法】BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!
【Bean方法:InitializingBean接口】调用InitializingBean.afterPropertiesSet()
【自身方法:init-method】调用<bean>的init-method属性指定的初始化方法
【容器方法】BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!
【容器方法】InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法
LOGGER测试:容器初始化成功
Person [address=广州, name=张三, phone=110]
LOGGER测试:现在开始关闭容器!
【Bean级别:DiposibleBean接口】调用DiposibleBean.destory()
【自身方法:destroy-method】调用<bean>的destroy-method属性指定的初始化方法

将Demo代码的执行结果与上述表中的执行时机进行对比,看看执行时机是否正确,

小结

理解透彻Spring Bean的生命周期对开发中可以解决比较棘手的问题,对于深入学习Spring Framework框架这是必须要掌握的知识,所以可以多看两遍。

该教程所属Java工程师之Spring Framework深度剖析专栏,本系列相关博文目录 Java工程师之Spring Framework深度剖析专栏

Spring Framework核心概念之Bean生命周期管理的更多相关文章

  1. 【Spring Framework】Spring IOC详解及Bean生命周期详细过程

    Spring IOC 首先,在此之前,我们就必须先知道什么是ioc,ioc叫做控制反转,也可以称为依赖注入(DI),实际上依赖注入是ioc的另一种说法, 1.谁控制谁?: 在以前,对象的创建和销毁都是 ...

  2. 从启动日志看Spring IOC的初始化和Bean生命周期

    一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是T ...

  3. spring bean生命周期管理--转

    Life Cycle Management of a Spring Bean 原文地址:http://javabeat.net/life-cycle-management-of-a-spring-be ...

  4. Spring-IOC bean 生命周期之 Lifecycle 钩子

    Lifecycle callbacks Initialization callbacks.Destruction callbacks 要与容器的bean生命周期管理交互,即容器在启动后和容器在销毁前对 ...

  5. beanFactory 设计模式 Bean 生命周期的胡言乱语,哈哈

    写在前面的话 适用读者:有一定经验的,本文不适合初学者,因为可能不能理解我在说什么 文章思路:不会一开始就像别的博客文章那样,Bean 的生命周期,源码解读(给你贴一大堆的源码).个人觉得应该由问题驱 ...

  6. beanFactory 设计模式 Bean 生命周期

    写在前面的话 适用读者:有一定经验的,本文不适合初学者,因为可能不能理解我在说什么 文章思路:不会一开始就像别的博客文章那样,Bean 的生命周期,源码解读(给你贴一大堆的源码).个人觉得应该由问题驱 ...

  7. Elasticsearch 快照生命周期管理 (SLM) 实战指南

    文章转载自:https://mp.weixin.qq.com/s/PSfgPJc4dKN2pOZd0Y02wA 1.Elasticsearch 保证高可用性的方式 Elasticsearch 保证集群 ...

  8. JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(6):Spring IOC容器学习(概念、作用、Bean生命周期)

    一.IOC控制反转概念 控制反转(IOC)是一种通过描述(在Java中可以是XML或者是注解)并通过第三方去生产或获取特定对象的方式. 主动创建模式,责任在于开发者,而在被动模式下,责任归于Ioc容器 ...

  9. spring(二、bean生命周期、用到的设计模式、常用注解)

    spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...

随机推荐

  1. JSON未定义

    用ajax实现了一个功能,在IE8和IE9中都能正常运行(大概是IE8和IE9都提供了原生的JSON解析和序列化),但是一旦切换到兼容模式就报JSON未定义的错误,解决方法是:判断当前浏览器是否支持J ...

  2. highcharts图表中级入门:非histock图表的highcharts图表如何让图表产生滚动条

    最近highcharts图表讨论群里面很多朋友都在问如何让highcharts图表在X轴数据多的情况下产生滚动条的问题,其实之前有一个解决办法是将装载图表的div容器用css样式表弄一个滚动条出来.这 ...

  3. wcf中的使用全双工通信(转)

    wcf中的使用全双工通信   wcf中的契约通信默认是请求恢复的方式,当客户端发出请求后,一直到服务端回复时,才可以继续执行下面的代码. 除了使用请求应答方式的通信外,还可以使用全双工.下面给出例子: ...

  4. RAC的搭建(一)--安装环境准备

    软硬件环境准备: 1.1 虚拟环境: VirtualBox上两个虚拟机,3G内存1核 1.2 软件环境: 数据库安装软件:p10404530_112030_LINUX_1of7.zip  p10404 ...

  5. 去掉a标签

    需求: 去掉网页中所有的a标签 方法一: str.replace(/(<\/?a.*?>)|(<\/?span.*?>)/g, '');//str为要修改的那段文字 方法二: ...

  6. #pragma init_seg

    先进后出原则,最先初始化的最后析构! 1.C++中全局对象.变量的构造函数调用顺序是跟声明有一定关系的,即在同一个文件中先声明的先调用.对于不同文件中的全局对象.变量,它们的构造函数调用顺序是未定义的 ...

  7. linux 下 java 链接oracle数据库

    import java.sql.*; public class Hello { private final String oracleDriverName = "oracle.jdbc.dr ...

  8. SQL Server设置登录验证模式

    我们在安装SQL Server的时候可以设置“混合验证模式”,既可以使用windows身份验证登录,也可以使用SQL Server身份验证登录. 如果我们在安装的时候并未设置"混合验证模式& ...

  9. vuex - 学习日记

    一.简单理解 简单说vuex,就是用来管理组件状态的数据,并且能在你可掌控的范围下增删改查这些数据. store容器 , state状态 二者关系(包含): 以前我也把vuex里边的state看成是一 ...

  10. linux下 php 安装mysql的扩展模块

    1.安装mysql-devel包 [root@DBproxy ~]# yum install mysql-devel 注:该包必须在编译php之前安装好,否则在安装php的mysql扩展模块是会碰到各 ...