Spring 学习笔记---Bean的生命周期
生命周期图解
窥探Bean生命周期的实例
package com.spring.beanfactory; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; public class Car implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean{
private String brand;
private String color;
private int maxSpeed;
private BeanFactory beanFactory;
private String beanName; public String getColor() {
return color;
} public void setColor(String color) {
this.color = color;
} public int getMaxSpeed() {
return maxSpeed;
} public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
} public String getBrand() {
return brand;
} public BeanFactory getBeanFactory() {
return beanFactory;
} public String getBeanName() {
return beanName;
} //1、管理Bean生命周期的接口
public Car(){
System.out.println("调用Car构造函数");
} public void setBrand(String brand) {
System.out.println("调用setBrand()设置属性");
this.brand = brand;
} public void introduce(){
System.out.println("bradn:"+brand+";color"+color+"; maxSpeed:"+maxSpeed);
} //2、BeanFactoryAware接口方法
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()");
this.beanFactory=beanFactory;
} //3、BeanNameAware接口方法
public void setBeanName(String beanName) {
System.out.println("调用BeanNameAware.setBeanName()");
this.beanName=beanName;
} //4 nitializingBean接口方法
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()");
} // 5 DisposableBean接口方法
public void destroy() throws Exception {
System.out.println("调用DisposableBean.destroy()");
} // 6 通过<bean>的init-method属性指定的初始化方法
public void myInit(){
System.out.println("调用inti-method所指定的myInit(),将maxSpeed设置为240.");
this.maxSpeed=240;
} //7 通过<bean>的destory-method属性指定的销毁方法
public void myDestory(){
System.out.println("调用destory-method所指定的myDestory()方法。");
}
}
InstantiationAwareBeanPostProcessor实现类
package com.spring.beanfactory; import java.beans.PropertyDescriptor; import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; @SuppressWarnings("unchecked")
public class MyInstantiationAwareBeanPostProcessor extends
InstantiationAwareBeanPostProcessorAdapter { //1 接口方法:实例化bean前进行调用
public Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {
//1-1仅对容器中的car-bean进行处理
if("car".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()");
} return null;
} //2 接口方法:在实例化bean后进行调用
public boolean postProcessAfterInstantiation(Object bean, String beanName )
throws BeansException{
if("car".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()");
}
return true;
} //3接口方法:在设置某个属性时调用
public PropertyValues postProcessPropertyValues(
PropertyValues propertyvalues,
PropertyDescriptor apropertydescriptor[], Object bean, String beanName)
throws BeansException{
//3-1仅对容器中car-bean进行处理,还可以通过post入参进行过滤,
//仅对car的某个特定属性进行处理
if("car".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues");
}
return propertyvalues;
}
}
BeanPostProcessor实现类
package com.spring.beanfactory; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor; public class MyBeanPostProcessor implements BeanPostProcessor { 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;
} 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(),将maxSpedd调整为200.");
car.setMaxSpeed(200);
}
}
return bean;
} }
在Spring配置文件中定义Car的配置信息
<?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.0.xsd"> <bean id="car" class="com.spring.beanfactory.Car" init-method="myInit" destroy-method="myDestory"
p:brand="红旗CA72"
p:maxSpeed="300"
scope="singleton"
/> </beans>
package com.spring.beanfactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; public class BeanLifeCycle { private static void LifiCycleInBeanFactory(){
// 1 下面两句装载配置文件,并启动容器
Resource res=new ClassPathResource("beans.xml");
BeanFactory bf=new XmlBeanFactory(res); // 2 向容器中注册MyBeanPostProcesser处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
//3 向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor()); //4 第一次从容器中获取car,将处罚容器实例化该Bean,这将引发Bean生命周期方法的调用
Car car1=(Car)bf.getBean("car");
car1.introduce();
car1.setColor("红色"); // 5第二次从容器中获取car,直接从缓存池中取(因为 scope="singleton")
Car car2=(Car)bf.getBean("car"); // 6 查看car1和car2是否指向同一引用
System.out.println("car1==car2"+(car1==car2)); // 7 关闭容器
((XmlBeanFactory)bf).destroySingletons(); } public static void main(String[] args) {
LifiCycleInBeanFactory();
} }
三月 27, 2014 11:16:39 上午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
调用Car构造函数
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
InstantiationAwareBeanPostProcessor.postProcessPropertyValues
调用setBrand()设置属性
调用BeanNameAware.setBeanName()
调用BeanFactoryAware.setBeanFactory()
调用BeanPostProcessor.postProcessBeforeInitialization(),color为空,设置为默认黑色.
调用InitializingBean.afterPropertiesSet()
调用inti-method所指定的myInit(),将maxSpeed设置为240.
调用BeanPostProcessor.postProcessAfterInitialization(),将maxSpedd调整为200.
bradn:红旗CA72;color黑色; maxSpeed:200
car1==car2true
三月 27, 2014 11:16:39 上午 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
信息: Destroying singletons in org.springframework.beans.factory.xml.XmlBeanFactory@1ed7c33: defining beans [car]; root of factory hierarchy
调用DisposableBean.destroy()
调用destory-method所指定的myDestory()方法。
仔细观察输出的信息,将发现它验证了我们前面所介绍的生命周期的过程。在7处,我们通过destroySingletons()方法关闭容器,由于Car实现了销毁接口并指定了销毁方法,所以容器将触发调用这两个方法.
ApplicationContext中Bean的生命周期
来看一个使用工厂后处理器的实例,假设我们希望对配置文件中car的brand配置属性进行调整,则可以编写一个如下的工厂后处理器:
package com.spring.context; 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;
import org.springframework.context.annotation.Bean; public class MyBeanFactoyPostProcessor implements BeanFactoryPostProcessor{
//1 对car<bean> 的brand属性配置信息进行“偷梁换柱”的加工操作
public void postProcessBeanFactory(
ConfigurableListableBeanFactory bf)
throws BeansException { BeanDefinition bd=bf.getBeanDefinition("car");
bd.getPropertyValues().addPropertyValue("brand", "奇瑞QQ");
System.out.println("调用BeanFactoryPostProcessor.postProcessBeanFactory()!");
}
}
<?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.0.xsd">
<!-- 1 这个brand属性的值将被工厂后处理器更改掉-->
<bean id="car" class="com.spring.beanfactory.Car" init-method="myInit" destroy-method="myDestory"
p:brand="红旗CA72"
p:maxSpeed="300"
/> <!-- 2 Bean后处理器-->
<bean id="myBeanPostprocessor" class="com.spring.beanfactory.MyBeanPostProcessor"/> <!-- 3 Bean工厂后处理器 -->
<bean id="myBeanFactory" class="com.spring.context.MyBeanFactoyPostProcessor"/>
</beans>
2和3处定义的BeanPostProcessor和BeanFactoryPostProcessor会自动被ApplicationContext识别并注册到容器中。3处注册的工厂后处理器将会对1处配置的属性值进行调整。在2处,我们还定义了一个Bean后处理器,它也可以对1处配置的属性进行调整。启动容器并查看car Bean的信息,我们将发现car Bean的brand属性成功被工厂后处理器修改了.
package com.spring.test; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.spring.beanfactory.Car;
public class Test {
public static void main(String[] args) { ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
Car car =(Car) ctx.getBean("car");
System.out.println(car.getBrand());
}
}
输出信息如下:
三月 27, 2014 1:55:54 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f1841: startup date [Thu Mar 27 13:55:54 CST 2014]; root of context hierarchy
三月 27, 2014 1:55:54 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
调用BeanFactoryPostProcessor.postProcessBeanFactory()!
三月 27, 2014 1:55:54 下午 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@16fb592: defining beans [car,myBeanPostprocessor,myBeanFactory]; root of factory hierarchy
调用Car构造函数
调用setBrand()设置属性
调用BeanNameAware.setBeanName()
调用BeanFactoryAware.setBeanFactory()
调用BeanPostProcessor.postProcessBeforeInitialization(),color为空,设置为默认黑色.
调用InitializingBean.afterPropertiesSet()
调用inti-method所指定的myInit(),将maxSpeed设置为240.
调用BeanPostProcessor.postProcessAfterInitialization(),将maxSpedd调整为200.
奇瑞QQ
Spring 学习笔记---Bean的生命周期的更多相关文章
- Spring4学习笔记 - Bean的生命周期
1 Spring IOC 容器对 Bean 的生命周期进行管理的过程: 1)通过构造器或工厂方法创建 Bean 实例 2)为 Bean 的属性设置值和对其他 Bean 的引用 3)调用 Bean 的初 ...
- (转)Spring管理的Bean的生命周期
http://blog.csdn.net/yerenyuan_pku/article/details/52834011 bean的初始化时机 前面讲解了Spring容器管理的bean的作用域.接着我们 ...
- MAVEN学习笔记之Maven生命周期和插件简介(3)
MAVEN学习笔记之Maven生命周期和插件简介(3) clean compile site三套生命周期相互独立. clean pre-clean 执行清理前的工作 clean 清理上一次构建生成的所 ...
- Spring 容器中 Bean 的生命周期
Spring 容器中 Bean 的生命周期 1. init-method 和 destory-method 方法 Spring 初始化 bean 或销毁 bean 时,有时需要作一些处理工作,因此 s ...
- spring深入学习(二)-----bean的生命周期、IOC容器bean装配
bean的生命周期 1.实例化Bean对于BeanFactory容器,当客户向容器请求一个尚未初始化的bean时,或初始化bean的时候需要注入另一个尚未初始化的依赖时,容器就会调用createBea ...
- (spring-第1回【IoC基础篇】)Spring容器中Bean的生命周期
日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...
- IoC基础篇(一)--- Spring容器中Bean的生命周期
日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此 ...
- Spring 学习笔记 Bean的作用域
在配置文件中定义Bean时,用户不但可以配置Bean的属性值以及相互之间的依赖关系,还可以定义Bean的作用域.作用域将对Bean的生命周期和创建方式产生影响.在低版本的Spring中,仅有两个作用域 ...
- Spring容器中bean的生命周期以及关注spring bean对象的后置处理器:BeanPostProcessor(一个接口)
Spring IOC 容器对 Bean 的生命周期进行管理的过程: 1.通过构造器或工厂方法创建 Bean 实例 2.为 Bean 的属性设置值和对其他 Bean 的引用 3.将 Bean 实例传递给 ...
随机推荐
- 【Hadoop 10周年】我与Hadoop不得不说的故事
什么是Hadoop 今年是2016年,是hadoop十岁的生日,穿越时间和空间,跟她说一声生日快乐,二千零八年一月二十八号,是一个特别的日子,hadoop带着第一声啼哭,来到了这个世界, ...
- JQuery之事件处理
JQuery不支持捕获模型 冒泡模型解析 <body> <div> <input id="bntShow" type="button&quo ...
- C语言获取文件大小
C语言是一种比较底层的语言,有时在其他语言中很容易操作的事情,在C语言中就比较麻烦,例如获取一个文件的大小.Java中File类有个length函数,Python中os.path包中有个getsize ...
- [mysql]一次主从数据不一致的问题解决过程
之前一篇: 主从更换ip之后重新建立同步 情况时这样的 昨天晚上主动2个机器都迁移了,然后今天才把主动重新连接上,但是从库的偏移量是从今天当前时刻开始的,也就是说虽然现在主动看似正常,其实是少了昨天的 ...
- Java-IO之字符输入输出流(Reader和Writer)
以字符为单位的输入流的公共父类是Reader: 以字符为单位的输出流的超类是Writer: 基于JDK8的Reader的源码: public abstract class Reader impleme ...
- 初识WCF之使用配置文件部署WCF应用程序
二月份的开头,小编依旧继续着项目开发之路,开始接触全新的知识,EF,WCF,MVC等,今天小编来简单的总结一下有关于WCF的基础知识,学习之前,小编自己给自己提了两个问题,WCF是什么?WCF能用来做 ...
- 精通CSS+DIV网页样式与布局--页面背景
上篇博客,我们主要简单的总结了CSS的图片效果,我们这回来讲讲CSS如何对网页的背景进行设置,网页的背景是整个网页的重要组成部分,她直接决定了整个网页的风格和色调.这篇博客简单的总结一下如何用CSS来 ...
- (NO.00004)iOS实现打砖块游戏(四):砖块类的实现
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 用Xcode打开之前SpriteBuilder创建的项目,我们现 ...
- gradle 修改生成的apk的名字
在app的module里的build.gradle文件中,在android { ...}里面加上这样一段代码,即可修改生成的apk的文件名. android.applicationVariants.a ...
- 95%的bug是由程序员造成的
原文作者:Jeff Atwood 作者在Twitter上发的一条短讯: "在怨天尤人之前,我们应该先自我反省.努力把自身的问题解决了." 12:22 PM –2012-5-30 你 ...