spring BeanFactory及ApplicationContext中Bean的生命周期
spring bean 的生命周期
spring BeanFactory及ApplicationContext在读取配置文件后、实例化bean前后、设置bean的属性前后这些点都可以通过实现接口添加我们自己的逻辑
spring BeanFactory中Bean的生命周期
demo1
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
</dependencies>
pom.xml
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*; /**
* BeanFactoryAware 觉察到
* InitializingBean 初始化
* Disposable 一次性的,可任意处理的; 用后就抛弃的
*
* BeanFactoryAware、BeanNameAware、InitializingBean、DisposableBean都是Bean级的生命周期控制接口
*/
public class Car implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
// 品牌
private String brand;
// 颜色
private String color;
// 最快速度
private int maxSpeed; public Car() {
System.out.println("构造方法执行");
} public void setBrand(String brand) {
System.out.println("setBrand方法执行");
this.brand = brand;
}
public String getColor() {
return this.color;
} public void setColor(String color) {
this.color = color;
} public int getMaxSpeed() {
return maxSpeed;
} public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
} public void introduce() {
System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:" + maxSpeed);
} private BeanFactory beanFactory;
@Override
// 实现BeanFactoryAware需要重写的唯一方法
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware接口定义的setBeanFactory方法");
this.beanFactory = beanFactory;
} private String beanName;
@Override
// 实现BeanNameAware需要重写的唯一方法
public void setBeanName(String beanName) {
System.out.println("调用BeanNameAware接口定义的setBeanName方法");
this.beanName = beanName;
} @Override
// 实现InitializingBean需要重写的唯一方法
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean接口定义的afterPropertiesSet方法");
} @Override
// 实现DisposableBean需要重写的唯一方法
public void destroy() throws Exception {
System.out.println("调用DisposableBean接口定义的destroy方法");
} // 通过<bean>的init-method属性指定的初始化方法
public void myInit() {
System.out.println("调用init-method指定的myInit方法,将maxSpeed设置为240");
this.maxSpeed = 240;
} // 通过<bean>的destroy-method属性指定的销毁方法
public void myDestroy() {
System.out.println("调用destroy-method指定的myDestroy方法");
}
}
Car.java
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; import java.beans.PropertyDescriptor; public class MyInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter {
/**
* 在实例化Bean前调用,仅对容器中的car Bean处理
*
* 父类实现了接口 SmartInstantiationAwareBeanPostProcessor,
* SmartInstantiationAwareBeanPostProcessor 又继承了接口 InstantiationAwareBeanPostProcessor
* InstantiationAwareBeanPostProcessor 又继承了 BeanPostProcessor
* 有方法postProcessBeforeInstantiation
*/
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("car".equals(beanName)) {
System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法执行");
}
return null;
} /**
* 在实例化Bean后调用,仅对容器中的car Bean处理
*
* 同上,InstantiationAwareBeanPostProcessor 有方法 postProcessAfterInstantiation
*/
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("car".equals(beanName)) {
System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法执行");
}
return true;
} /**
* 在设置某个属性时调用,仅对car Bean的品牌属性值进行处理,还可以通过pds入参进行过滤
*
* 同上,InstantiationAwareBeanPostProcessor 有方法 postProcessPropertyValues
*/
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
if ("car".equals(beanName)) {
System.out.println("InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法执行");
}
return pvs;
}
}
MyInstantiationAwareBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; /**
* processor 加工,处理
* BeanPostProcessor后处理器在spring框架中占有重要的地位,这是容器对Bean进行后续加工处理的切入点;
* spring提供的动态代理、AOP都是通过BeanPostProcessor实现的
*/
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("car")) {
Car car = (Car)bean;
if (car.getColor() == null) {
System.out.println("调用接口BeanPostProcessor的postProcessBeforeInitialization方法," +
"color为空,设置为默认黑色");
car.setColor("黑色");
}
}
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals("car")) {
Car car = (Car)bean;
if (car.getMaxSpeed() >= 200) {
System.out.println("调用接口BeanPostProcessor的postProcessAfterInitialization方法," +
"将maxSpeed调整为200");
car.setMaxSpeed(200);
}
}
return bean;
}
}
MyBeanPostProcessor
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="car" class="Car" init-method="myInit" destroy-method="myDestroy"
p:brand="宝马373" p:maxSpeed="220"/> </beans>
my.xml
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource; /**
* 测试类
*/
public class BeanLifeCycle { public static void main(String[] args) {
lifeCycleBeanFactory();
} private static void lifeCycleBeanFactory() {
// 装载配置文件
ClassPathResource resource = new ClassPathResource("my.xml"); // 启动容器
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory) beanFactory);
reader.loadBeanDefinitions(resource); // 向容器中注册MyBeanPostProcessor后处理器
((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyBeanPostProcessor());
// 向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory)beanFactory).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor()); // 第一次从容器中获取car,将触发容器实例化这个Bean,这将引发Bean生命周期方法的调用
Car car1 = (Car)beanFactory.getBean("car");
car1.introduce();
car1.setColor("红色"); // 第二次从容器中获取car,直接从缓存池中获取
Car car2 = (Car) beanFactory.getBean("car"); // 查看car1和car2是否指向同一引用
System.out.println("car1==car2:" + (car1 == car2)); ((DefaultListableBeanFactory)beanFactory).destroySingletons();
}
}
测试类
1、InstantiationAwareBeanPostProcessor 接口的 postProcessBeforeInstantiation 方法执行
构造方法执行
2、InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 方法执行
3、InstantiationAwareBeanPostProcessor 接口的 postProcessPropertyValues 方法执行
setBrand方法执行
4、调用BeanNameAware接口定义的setBeanName方法
5、调用BeanFactoryAware接口定义的setBeanFactory方法
6、调用接口BeanPostProcessor的postProcessBeforeInitialization方法,color为空,设置为默认黑色
7、调用InitializingBean接口定义的afterPropertiesSet方法
8、调用init-method指定的myInit方法,将maxSpeed设置为240
9、调用接口BeanPostProcessor的postProcessAfterInitialization方法,将maxSpeed调整为200
brand:宝马373;color:黑色;maxSpeed:200
car1==car2:true
10、调用DisposableBean接口定义的destroy方法
11、调用destroy-method指定的myDestroy方法 输出分析:
在一个bean实例化之间之后,调用1、2。
1的方法入参是Class<?> beanClass, String beanName,分别对应bean的class和id
2的方法入参是Object bean, String beanName,分别对应实例化好的bean和bean的id 在属性填充前,调用3。
3的方法入参是PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName
pvs里封装着属性值,pds里封装着属性名,bean是实例化后的bean,beanName是bean的id 属性填充后,调用4、5。
4的方法入参是String beanName,可以把beanName也就是bean的id缓存起来,保存为一个成员变量
5的方法入参是BeanFactory beanFactory,可以把beanFactory缓存起来,保存为一个成员变量 在bean初始化之前之后调用6、9,这是BeanPostProcessor的方法,可以修改属性值,可以添加AOP
7、8是初始化方法
10、11是销毁方法
运行输出分析
其中的BeanPostProcessor接口非常重要,spring的动态代理、AOP都是通过实现这个接口而为bean添加行为的
spring ApplicationContext中Bean的生命周期
Spring Bean在ApplicationContext和BeanFactory中的生命周期类似。
不同的是,如果Bean实现了org.springframework.context.ApplicationContextAware接口,会增加一个调用该接口方法setApplicationContext()的步骤。
并且多了BeanFactoryPostProcessor接口,如果实现了该接口,ApplicationContext在装载配置文件之后、实例化Bean之前将调用该实现类的方法,对配置信息进行加工处理。Spring框架提供了多个工厂后处理器,如CustomEditorConfigurer、PopertyPlaceholderConfigurer等。工厂后处理器是容器级的,仅在ApplicationContext初始化时调用一次。
ApplicationContext在启动时,将首先为配置文件中的每个<bean>生成一个BeanDefinition对象,BeanDefinition是<bean>在Spring容器中的内部表示。当配置文件中所有的<bean>都被解析为BeanDefinition时,ApplicationContext将调用工厂后处理器的方法,因些,我们有机会通过程序的方式调整Bean的配置信息。
ApplicationContext和BeanFactory的一个最大的不同之处在于,前者会利用Java反射机制自动识别出配置文件中定义的BeanPostProcessor、InstantiationAwareBeanPostProcessor及BeanFactoryPostProcessor,并自动将它们注册到ApplicatContext中(在ApplicatContext中,只需在配置文件中通过<bean>定义工厂后处理器和Bean后处理器,它们就会按预期的方式运行);而后者需要在代码中手工调用addBeanProcessor()方法进行注册。
demo2——BeanFactoryPostProcessor
还使用demo1那个例子的代码,添加了MyBeanFactoryPostProcessor的实现、修改了my.xml、修改了测试类
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
// 实现BeanFactoryPostProcessor需要重写的唯一方法
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("car");
beanDefinition.getPropertyValues().addPropertyValue("brand", "吉利博瑞");
System.out.println("调用BeanFactoryPostProcessor的postProcessBeanFactory方法");
}
}
MyBeanFactoryPostProcessor
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="car" class="Car" init-method="myInit" destroy-method="myDestroy"
p:brand="宝马373" p:maxSpeed="220"/> <bean class="MyBeanPostProcessor"/> <bean class="MyInstantiationAwareBeanPostProcessor"/> <bean class="MyBeanFactoryPostProcessor"/> </beans>
my.xml
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; /**
* 测试类
*/
public class BeanLifeCycle { public static void main(String[] args) {
lifeCycleBeanFactory();
} private static void lifeCycleBeanFactory() {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:my.xml"); Car car1 = (Car)context.getBean("car");
car1.introduce();
car1.setColor("红色"); // 第二次从容器中获取car,直接从缓存池中获取
Car car2 = (Car) context.getBean("car"); // 查看car1和car2是否指向同一引用
System.out.println("car1==car2:" + (car1 == car2)); ((ClassPathXmlApplicationContext)context).destroy();
}
}
测试类
demo3——BeanFactoryPostProcessor
通过程序的方式调整Bean的配置信息
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.16.RELEASE</version>
</dependency>
pom.xml
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Driver {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("my.xml");
Boss boss1 = context.getBean("boss1", Boss.class);
Boss boss2 = context.getBean("boss2", Boss.class); System.out.println(boss1);
System.out.println(boss2);
}
}
class Boss {
private Car car; public Car getCar() {
return car;
} public void setCar(Car car) {
this.car = car;
}
}
class Car { }
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory; /**
* BeanPostProcessor
* Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
* Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
*
* BeanFactoryPostProcessor
* void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
*
* BeanPostProcessor和BeanFactoryPostProcessor是两个不同的接口:
* BeanPostProcessor是在Bean实例化后、属性设置后执行,是Spring AOP 的赖以实现的基础;
* BeanFactoryPostProcessor是WebApplicationContext读取配置文件后,还没有初始化任何实例时运行,
* 可以用来修改配置文件
*
*/
public class UserServiceFactoryBean implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
// 把ConfigurableListableBeanFactory转化为DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) bf;
// 通过BeanDefinitionBuilder创建bean定义
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Boss.class);
// 设置属性userDao,此属性引用已经定义的bean:car
beanDefinitionBuilder.addPropertyReference("car", "car");
// 注册bean定义
beanFactory.registerBeanDefinition("boss1", beanDefinitionBuilder.getRawBeanDefinition());
// 直接注册一个bean实例
beanFactory.registerSingleton("boss2", new Boss());
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="car" class="Car"/> <bean class="UserServiceFactoryBean"/> </beans>
spring BeanFactory及ApplicationContext中Bean的生命周期的更多相关文章
- ApplicationContext中Bean的生命周期
引言 Bean应用上下文中的生命周期和在BeanFactory中生命周期类似,不同的是,如果Bean实现了org.springframework.context.ApplicationContextA ...
- Spring学习-- IOC 容器中 bean 的生命周期
Spring IOC 容器可以管理 bean 的生命周期 , Spring 允许在 bean 声明周期的特定点执行定制的任务. Spring IOC 容器对 bean 的生命周期进行管理的过程: 通过 ...
- 【学习笔记】Spring中的BeanFactory和ApplicationContext 以及 Bean的生命周期(Y2-3-2)
BeanFactory和ApplicationContext Spring的IoC容器就是一个实现了BeanFactory接口的可实例化类. Spring提供了两种不同的容器: 一种是最基本的Bean ...
- 好记性不如烂笔头86-spring3学习(7)-ApplicationContext中bean的生命周期
假设使用ApplicationContext来生成.管理Bean, 一个Bean从建立到销毁,会历经几个运行阶段. 我个人理解一般的bean的生命周期主要包含:建立,初始化,使用阶段,销毁四个核心阶段 ...
- Spring重点—— IOC 容器中 Bean 的生命周期
一.理解 Bean 的生命周期,对学习 Spring 的整个运行流程有极大的帮助. 二.在 IOC 容器中,Bean 的生命周期由 Spring IOC 容器进行管理. 三.在没有添加后置处理器的情况 ...
- spring ApplicationContext中Bean的生命周期
AbstractApplicationContext Spring的AbstractApplicationContext是ApplicationContext的抽象实现类,该抽象类的refresh方法 ...
- (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期
日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...
- IoC基础篇(一)--- Spring容器中Bean的生命周期
日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...
- JAVA面试题:Spring中bean的生命周期
Spring 中bean 的生命周期短暂吗? 在spring中,从BeanFactory或ApplicationContext取得的实例为Singleton,也就是预设为每一个Bean的别名只能维持一 ...
随机推荐
- Testing - 软件测试知识汇总
软件测试知识梳理 基础概念 : http://www.cnblogs.com/anliven/p/6070000.html 测试分类 : http://www.cnblogs.com/anliven/ ...
- GMM基础
一.单成分单变量高斯模型 二.单成分多变量高斯模型 若协方差矩阵为对角矩阵且对角线上值相等,两变量高斯分布的等值线为圆形. 若协方差矩阵为对角矩阵且对角线上值不等,两变量高斯分布的等值线为椭圆形, 长 ...
- 昕有灵犀-xyFS私有文件云存储OSS服务
本工程为本人开发的开源项目,地址: https://gitee.com/475660/xyFS 介绍: 一站式企业私有文件服务.针对软件开发时提供的文件存储系统,对文件上传.下载.分类.分组.审计.统 ...
- Neo4j学习笔记
1. 环境搭建 正好最近同学有一台阿里云服务器借我玩,就尝试着在服务器上搭了Neo4j. 环境:CentOS Linux release 7.4.1708 (Core) 安装Java 安装Neo4j需 ...
- 从零开始学 Web 之 HTML5(一)HTML5概述,语义化标签
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- 内核开发知识第二讲,编写Kerner 程序中注意的问题.
一丶函数多线程的安全问题 什么是函数多线程安全. 简单来说就是 ,一个函数在调用过程中.还没有返回的时候.再次被其他线程调用了.但是函数执行的结果是可靠的.就可以了说这个函数是安全的. 比如我们在用户 ...
- elasticsearch数据过期删除处理
一.概述 使用elasticsearch收集日志进行处理,时间久了,很老的数据就没用了或者用途不是很大,这个时候就要对过期数据进行清理.这里介绍两种方式清理这种过期的数据. 1.curator 关于版 ...
- php处理文件的思考(去除空行、每行多余字符)
1.去除空行 <?php $str = file_get_contents('a.txt'); $str = explode(PHP_EOL, $str); //分割为数组,每行为一个数组元素 ...
- C++ 重载运算符简单举例
我们可以重定义或重载大部分 C++ 内置的运算符.这样,就能使用自定义类型的运算符. 重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的.与其他函数一 ...
- Linux终端命令全面介绍
Linux终端命令 一.文件目录类 1.建立目录:mkdir 目录名2.删除空目录:rmdir 目录名3.无条件删除子目录: rm -rf 目录名4.改变当前目录:cd 目录名 (进入用户home目录 ...