精通Spring 4.x企业应用开发实战(第四章之二 Bean的生命周期)——读书笔记
根据个人学习情况,筛选出特别关注的信息,完整内容请看原版,仅仅是个人学习笔记。
目录
3)自定义后处理器MyInstantiationAwareBeanPostProcessor
二)ApplicationContext中Bean的生命周期
三)BeanFactory和ApplicationContext的不同之处
一)BeanFactory中Bean的生命周期
以下为代码示例:
0)项目目录结构
1)beans.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-4.0.xsd">
<bean id="bigCar" class="com.imooc.demo.beanfactory.BigCar"
init-method="myInit"
destroy-method="myDestory"
p:brand="红旗CA72"
p:maxSpeed="200"
/>
</beans>
2)Bean装载的 BigCar类
package com.imooc.demo.beanfactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;
public class BigCar implements BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
private String brand;
private String color;
private int maxSpeed;
private BeanFactory beanFactory;
private String beanName;
public BigCar() {
System.out.println("调用BigCar类的构造函数");
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
System.out.println("调用setBrand()设置属性:" + brand);
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
System.out.println("调用setColor()设置属性:" + color);
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
System.out.println("调用setMaxSpeed()设置属性:" +maxSpeed);
this.maxSpeed = maxSpeed;
}
public void introduce(){
System.out.println("introduce:"+this.toString());
}
@Override
public String toString() {
return "brand:" + brand + "/color:" + color + "/maxSpeed:"+ maxSpeed;
}
// BeanFactoryAware接口方法
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用BeanFactoryAware.setBeanFactory()。");
this.beanFactory = beanFactory;
}
// BeanNameAware接口方法
@Override
public void setBeanName(String s) {
System.out.println("调用BeanNameAware.setBeanName()。");
this.beanName = beanName;
}
@Override
public void destroy() throws Exception {
System.out.println("调用DisposableBean.destory()。");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("调用InitializingBean.afterPropertiesSet()。");
}
public void myInit() {
System.out.println("调用myInit(),将maxSpeed设置为240。");
this.maxSpeed = 240;
}
public void myDestory() {
System.out.println("调用myDestroy()。");
}
}
3)自定义后处理器MyInstantiationAwareBeanPostProcessor
package com.imooc.demo.beanfactory;
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前调用
@Override
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
//仅对容器中的car Bean特殊处理
if("bigCar".equals(beanName)){
System.out.println("MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation");
}
return null;
}
//②接口方法:在实例化Bean后调用
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
//仅对容器中的car Bean特殊处理
if("bigCar".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation");
}
return true;
}
//③接口方法:在设置某个属性时调用
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
throws BeansException {
//仅对容器中的car Bean进行特殊处理,还可以通过pdst入参进行过滤
if("bigCar".equals(beanName)){
System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues");
}
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
4)自定义后处理器MyBeanPostProcessor
package com.imooc.demo.beanfactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("bigCar")){
BigCar car = (BigCar)bean;
if(car.getColor() == null){
System.out.println("调用MyBeanPostProcessor.postProcessBeforeInitialization(),color为空,设置为默认黑色。");
car.setColor("黑色");
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(beanName.equals("bigCar")){
BigCar car = (BigCar)bean;
if(car.getMaxSpeed() >= 200){
System.out.println("调用MyBeanPostProcessor.postProcessAfterInitialization(),将maxSpeed调整为200。");
car.setMaxSpeed(200);
}
}
return bean;
}
}
5)测试示例
package com.imooc.demo.beanfactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
public class BeanLifeCycle {
private static void LifeCycleInBeanFactory() {
//①下面两句装载配置文件并启动容器
Resource res = new ClassPathResource("beans.xml");
BeanFactory bf= new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)bf);
reader.loadBeanDefinitions(res);
//②向容器中注册MyBeanPostProcessor后处理器
((DefaultListableBeanFactory) bf).addBeanPostProcessor(new MyBeanPostProcessor());
//③向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
((DefaultListableBeanFactory) bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
//④第一次从容器中获取bigCar(beans.xml中bean的ID),将触发容器实例化该Bean,这将引发Bean生命周期方法的调用。
BigCar bigCar1 = (BigCar) bf.getBean("bigCar");
bigCar1.introduce();
bigCar1.setColor("红色");
//⑤第二次从容器中获取bigCar(beans.xml中bean的ID),直接从缓存池中获取
BigCar bigCar2 = (BigCar) bf.getBean("bigCar");
bigCar1.introduce();
bigCar2.introduce();
//⑥查看car1和car2是否指向同一引用
System.out.println("bigCar1==bigCar2:"+(bigCar1==bigCar2));
//⑦关闭容器
((DefaultListableBeanFactory) bf).destroySingletons();
}
public static void main(String[] args) {
LifeCycleInBeanFactory();
}
}
6)运行结果
MyInstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
调用BigCar类的构造函数
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'bigCar' to allow for resolving potential circular references
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
InstantiationAwareBeanPostProcessor.postProcessPropertyValues
调用setBrand()设置属性:红旗CA72
调用setMaxSpeed()设置属性:200
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用MyBeanPostProcessor.postProcessBeforeInitialization(),color为空,设置为默认黑色。
调用setColor()设置属性:黑色
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'bigCar'
调用InitializingBean.afterPropertiesSet()。
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking init method 'myInit' on bean with name 'bigCar'
调用myInit(),将maxSpeed设置为240。
调用MyBeanPostProcessor.postProcessAfterInitialization(),将maxSpeed调整为200。
调用setMaxSpeed()设置属性:200
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'bigCar'
introduce:brand:红旗CA72/color:黑色/maxSpeed:200
调用setColor()设置属性:红色
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'bigCar'
introduce:brand:红旗CA72/color:红色/maxSpeed:200
introduce:brand:红旗CA72/color:红色/maxSpeed:200
bigCar1==bigCar2:true
14:13:55.727 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.s[email protected]1fc2b765: defining beans [bigCar]; root of factory hierarchy
1 [main] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy() on bean with name 'bigCar'
调用DisposableBean.destory()。
[main] DEBUG org.springframework.beans.factory.support.DisposableBeanAdapter - Invoking destroy method 'myDestory' on bean with name 'bigCar'
调用myDestroy()。
二)ApplicationContext中Bean的生命周期
0)项目目录结构
1)添加工厂后处理器
package com.imooc.demo.beanfactory.applicationcontext;
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;
/**
* <p>标题: </p>
* <p>描述: 声明工厂后处理器接口BeanFactoryPostProcessor</p>
* <p>描述: 应用上下文在装载配置文件之后、初始化Bean实例之前将调用这些BeanFactoryPostProcessor对配置信息进行加工处理</p>
*/
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory bf) throws BeansException {
BeanDefinition bd = bf.getBeanDefinition("car");
//对brand属性进行加工操作
bd.getPropertyValues().addPropertyValue("brand","奇瑞QQ");
System.out.println("调用BeanFactroyPostProcessor.postProcessBeanFactory()");
}
}
2)工厂后处理器的配置
<!-- ApplicationContext注册Bean后处理器 -->
<bean id="myBeanPostProcessor" class="com.imooc.demo.beanfactory.MyBeanPostProcessor"/>
<!-- ApplicationContext注册Bean后处理器 -->
<bean id="myBeanFactoryPostProcessor" class="com.imooc.demo.beanfactory.applicationcontext.MyBeanFactoryPostProcessor"/>
3)测试示例
public class AnnotationApplicationContext {
public static void main(String[] args) {
// ApplicationContext ctx = new AnnotationConfigApplicationContext(BigCar.class);
ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
BigCar car =ctx.getBean("car",BigCar.class);
car.introduce();
car.setColor("蓝色");
car.introduce();
System.out.println("-------------- end ------------------");
}
}
4)运行结果
调用BigCar类的构造函数
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Eagerly caching bean 'car' to allow for resolving potential circular references
调用setBrand()设置属性:奇瑞QQ
调用setMaxSpeed()设置属性:200
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用MyBeanPostProcessor.postProcessBeforeInitialization(),color为空,设置为默认黑色。
调用setColor()设置属性:黑色
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'car'
调用InitializingBean.afterPropertiesSet()。
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking init method 'myInit' on bean with name 'car'
调用myInit(),将maxSpeed设置为240。
调用MyBeanPostProcessor.postProcessAfterInitialization(),将maxSpeed调整为200。
调用setMaxSpeed()设置属性:200
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'car'
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'myBeanPostProcessor'
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'myBeanFactoryPostProcessor'
[main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [[email protected]06c0b]
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
[main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
[main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning cached instance of singleton bean 'car'
introduce:brand:奇瑞QQ/color:黑色/maxSpeed:200
调用setColor()设置属性:蓝色
introduce:brand:奇瑞QQ/color:蓝色/maxSpeed:200
-------------- end ------------------
三)BeanFactory和ApplicationContext的不同之处
ApplicationContext:利用Java反射机制自动识别配置文件中定义的巩华城那个后处理器BeanPostProcessor、InstantiationAwareBeanPostProcessor和BeanFactoryPostProcessor,并自动注册到应用上下文中。
为了让Bean绑定在Spring框架上,推荐使用配置的方式而非接口方式进行生命周期的控制。
BeanFactory:在代码中通过手工调用addBeanPostProcessor()方法进行注册,相对比较麻烦。