Spring Framework核心概念之Bean生命周期管理
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
接口实现注入容器,再将容器后处理器InstantiationAwareBeanPostProcessor
和BeanPostProcessor
注入容器,又在自定义Person
实现了Bean级后处理器BeanNameAware
,BeanFactoryAware
,InitializingBean
和DiposableBean
接口的相关方法,最后就是在自定义的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生命周期管理的更多相关文章
- 【Spring Framework】Spring IOC详解及Bean生命周期详细过程
Spring IOC 首先,在此之前,我们就必须先知道什么是ioc,ioc叫做控制反转,也可以称为依赖注入(DI),实际上依赖注入是ioc的另一种说法, 1.谁控制谁?: 在以前,对象的创建和销毁都是 ...
- 从启动日志看Spring IOC的初始化和Bean生命周期
一.Tomcat中启动IoC容器的日志 启动Tomcat等容器时,控制台每次都打印出一些日志. 最近刚好在研究Spring源码,所以换个角度,从启动日志来简单的看看Spring的初始化过程! 以下是T ...
- spring bean生命周期管理--转
Life Cycle Management of a Spring Bean 原文地址:http://javabeat.net/life-cycle-management-of-a-spring-be ...
- Spring-IOC bean 生命周期之 Lifecycle 钩子
Lifecycle callbacks Initialization callbacks.Destruction callbacks 要与容器的bean生命周期管理交互,即容器在启动后和容器在销毁前对 ...
- beanFactory 设计模式 Bean 生命周期的胡言乱语,哈哈
写在前面的话 适用读者:有一定经验的,本文不适合初学者,因为可能不能理解我在说什么 文章思路:不会一开始就像别的博客文章那样,Bean 的生命周期,源码解读(给你贴一大堆的源码).个人觉得应该由问题驱 ...
- beanFactory 设计模式 Bean 生命周期
写在前面的话 适用读者:有一定经验的,本文不适合初学者,因为可能不能理解我在说什么 文章思路:不会一开始就像别的博客文章那样,Bean 的生命周期,源码解读(给你贴一大堆的源码).个人觉得应该由问题驱 ...
- Elasticsearch 快照生命周期管理 (SLM) 实战指南
文章转载自:https://mp.weixin.qq.com/s/PSfgPJc4dKN2pOZd0Y02wA 1.Elasticsearch 保证高可用性的方式 Elasticsearch 保证集群 ...
- JavaEE互联网轻量级框架整合开发(书籍)阅读笔记(6):Spring IOC容器学习(概念、作用、Bean生命周期)
一.IOC控制反转概念 控制反转(IOC)是一种通过描述(在Java中可以是XML或者是注解)并通过第三方去生产或获取特定对象的方式. 主动创建模式,责任在于开发者,而在被动模式下,责任归于Ioc容器 ...
- spring(二、bean生命周期、用到的设计模式、常用注解)
spring(二.bean生命周期.用到的设计模式.常用注解) Spring作为当前Java最流行.最强大的轻量级框架,受到了程序员的热烈欢迎.准确的了解Spring Bean的生命周期是非常必要的. ...
随机推荐
- Python 面向对象详解
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的.本章节我们将详细介绍Python的面向对象编程. 如果你以前没有接触过面向对象的编程语言,那你 ...
- MySQL修改密码和忘记ROOT密码
1.关闭数据库 脚本:[root@mysql etc]# service mysql stop 2.使用脚本: mysqld_safe --skip-grant-tables 启动数据库 使用/usr ...
- C#爬网页时“远程服务器返回错误: (403) 已禁止”解决方法
HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(uri); //这个一定要加上,在某些网站没有会发生"远程服务器返回错误: ...
- [原]unity3d 纹理旋转
纹理旋转实现思路:纹理坐标*平移矩阵*旋转矩阵(类似顶点旋转): 矩阵一般要求中心点为(0,0) 而纹理中心点默认(0.5,0.5);所以先得平移到(0,0):可以考虑乘以平移矩阵[1,0,0,0,1 ...
- create a cocos2d-x-3.0 project in Xcode
STEP1: Open Terminal SETP2: Run setup.py SETP3: Run source /Users/your_user/.bash_profile( so that e ...
- MySQL------如何关闭打开MySQL
1.win+R打开运行窗口,输入services.msc 2.在其中查看mysql的服务名,我的是MySQL57 3.以管理员身份打开cmd 停止: 输入net stop MySQL57 启动: 输入 ...
- Tomcat------如何查看80端口是否被占用
1.Window + R,打开“运行”窗口,输入cmd 2.输入netstat -nao,回车,一般来说80端口会被PID为4的程序占用 3.启动任务管理器,点击“查看”->“选择列” 4.勾选 ...
- AppStore应用转让流程
可能大家都有这样的情况,给公司客户开发一个ios app的前期阶段是先发布在自己公司的开发者账户上面的,而不是直接发布在客户的开发者账号上面,这个到后期的话就有一个转让的事情,俗称“过户”. 步骤如下 ...
- 8 -- 深入使用Spring -- 3...1 Resource实现类UrlResource
8.3.1 Resource 实现类------UrlResource : 访问网络资源的实现类 1.访问网络资源 访问网络资源通过UrlResource 类实现,UrlResource是java.n ...
- C#中的Abstract、Virtual、Interface理解
容易混淆是必须的,都是与继承有关系,并且涉及到override的使用 一.Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中 ...