Spring学习5(3):Bean的生命周期

Spring学习5(3)

 Bean生命周期由多个特定的生命阶段组成,每个生命阶段都开出接口,允许外界由此对Bean施加控制。
 在spring中有两个层面来定义Bean的生命周期,一个是Bean的作用范围,一个是实例化Bean时所经历的一系列阶段。

BeanFactory中Bean的生命周期

生命周期图解

在这里插入图片描述

 具体调用过程如下:

  1. 当调用getBean()来请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口则会在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法。
  2. 根据配置情况调用Bean构造函数或工厂方法实例化Bean。
  3. 如果容器注册了在步骤1中的那个接口那么在实例化Bean后,可以调用接口的postProcessAfterInstantiation()方法来对已经实例化的对象做一点“梳妆打扮”。
  4. 如果Bean配置了属性信息,那么容器在这一步将配置值设置到Bean对应属性中,不过在设置每个属性之前可以调用步骤1接口的postProcessPropertyValues()方法。
  5. 调用Bean的属性设置方法设置属性值。
  6. 如果Bean实现了org.springframework.bean.factory.BeanNameAware接口则将调用setBeanName()接口方法,将配置文件中该Bean对应的名称设置到Bean中。
  7. 如果Bean实现了org.springframework.beans.factory.BeanFactoryAware则将嗲用setBeanFactory()方法将BeanFactory容器实例设置到Bean中。
  8. 如果BeanFactory装配了org.springframework.beans.factory.config.BeanPostProcessor,则调用BeanPostProcessor的Objetc:postProcessBeforeInitialization(Object bean, String beanName)这个函数提供当前正在处理的Bean以及beanName(当前Bean的配置名)返回加工处理后的Bean。这个方法可以对某些Bean进行特殊的处理,甚至改变Bean的行为,是spring框架中的重要方法,为容器提供对Bean进行后续加工处理的切入点,spring容器所提供的各种功能如Aop,动态代理等都经过BeanPostProcessor来实施。
  9. 如果Bean实现了InitializingBean的接口afterPropertiesSet()方法。
  10. 如果在<bean>中通过了init-method定义了初始化方法,则将执行这个方法。
  11. BeanPostProcessor除了步骤8中的方法还定义了postProcessAfterInitialization(Object bean, String beanName)方法,此时会调用这个方法让容器再次获得对Bean进行加工的机会。
  12. 如果在<bean>中指定Bean的作用范围为scope="prototype"则将Bean返回给调用者,spring不再管理Bean的生命周期;如果指定为scope="singletion"则将Bean放入springIoC容器的缓存池中,并将Bean引用放回给调用者,spring继续对这些Bean进行后续的生命管理。
  13. 对于scope="singleton"的Bean(默认情况),当容器关闭时,如果Bean实现了DisposableBean接口,则将调用接口的destory()方法,可以在此编写释放资源,记录日志等操作。
  14. 对于scope="singletion"的Bean,如果通过<bean>的destroy-method属性指定了Bean的销毁方法,那么Spring将执行Bean的这个方法,完成Bean资源的释放。

Bean生命周期实例

 采用之前用过的Car类,让它实现所有Bean级的生命接口。
 我们修改com.smart下Car.java文件为如下代码:

package com.smart;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.BeanNameAware;
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 Car() {
		System.out.println("调用Car()构造函数。");
		
	}
	
	public Car(String brand, String color, int maxSpeed) {
		this.brand = brand;
		this.color = color;
		this.maxSpeed = maxSpeed;
	}
	
	public void introduce() {
		System.out.println("brand:"+brand+";color:"
				+ color+";maxSpeed:"
				+ maxSpeed+".");
	}
	
	public void setBrand(String brand) {
		this.brand = brand;
		System.out.println("调用setBrand()设置属性。");
	}
	
	public void setColor(String color) {
		this.color = color;
		System.out.println("调用setColor()设置属性。");
	}
	
	public void setMaxSpeed(int maxSpeed) {
		this.maxSpeed = maxSpeed;
		System.out.println("调用setMaxSpeed()设置属性。");
	}
	
	//BeanFactoryAwawre接口方法
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException{
		System.out.println("调用BeanFactoryAware.setBeanFactory().");
		this.beanFactory = beanFactory;
	}
	
	//BeanNameAware接口方法
	public void setBeanName(String beanName) {
		System.out.println("调用BeanNameAware.setBeanName().");
		this.beanName = beanName;
	}
	
	//InitializingBean接口方法
	public void afterPropertiesSet() throws Exception{
		System.out.println("调用InitializingBean.afterPropertiesSet().");
		
	}
	
	//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().");
	}
}

 这里实现了BeanFactoryAware, BeanNameAware,InitializingBean,DisposableBean等Bean级的生命周期接口,在下面定义了myInit()和myDestroy()方法,这两个方法就可以在<bean>中通过init-method和destroy-method方法。

 MyInstantiationAwareBeanPostProcessor通过扩展InstantiationAwareBeanPostProcessor适配器InstatiationAwareBeanPostProcessorAdapter提供实现。我们在com.smart.beanfactory中增加myInstantiationAwareBeanPostProcessor.java,代码如下:

package com.smart.beanfactory;
import java.beans.PropertyDescriptor;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.
InstantiationAwareBeanPostProcessorAdapter;
import com.smart.Car;
public class MyInstantiationAwareBeanPostProcessor extends 
InstantiationAwareBeanPostProcessorAdapter{
	
	//接口:在实例化Bean前调用
	public Object postProcessBeforeInstantiation(Class beanClass, String beanName)
		throws BeansException{
		if("car1".equals(beanName)) {
			System.out.println("InstantiationAware BeanPostProcessor.postProcess"
					+ "	BeforeInstantiation");
		}
		return null;
	}
	
	//接口:在实例化Bean后调用
	public boolean postProcessAfterInstantiation(Object bean, String beanName)
		throws BeansException{
		if("car1".equals(beanName)) {
			System.out.println("InstantiationAware BeanPostProcessor.postProcess"
					+ "		AfterInstantiation");
		}
		return true;
	}
	//接口:在设置某个属性时调用
	public PropertyValues postProcessPropertyValues(
		PropertyValues pvs,PropertyDescriptor[] pds, Object bean, String beanName)
		throws BeansException{
		if("car1".equals(beanName)) {
			System.out.println("Instantiation AwareBeanPostProcessor.postProcess"
					+ "PropertyValues");
		}
		return pvs;
	}
}

 除此之外spring还有一个BeanPostProcessor实现类,对配置文件所提供的属性设置值进行判断,并执行相应的“补缺补漏操作”,在代码清单如下:

package com.smart.beanfactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import com.smart.Car;
public class MyBeanPostProcessor implements BeanPostProcessor{
	public Object postProcessBeforeInitialization(Object bean, String beanName)
		throws BeansException{
		if(beanName.equals("car1")) {
			Car car = (Car)bean;
			if(car.getColor() == null) {
				System.out.println("调用BeanPostProcessor.postProcess"
						+ "	BeforeInitialization(), color is empty, default color is black");
				car.setColor("黑色");
				
			}
		}
		return bean;
	}
	
	public Object postProcessAfterInitialization(Object bean, String beanName)
		throws BeansException{
		if(beanName.equals("car1")) {
			Car car = (Car)(bean);
			if(car.getMaxSpeed() >= 200) {
				System.out.println("调用BeanPostProcessor.postProcess"
						+ "AfterInitialization(), modify maxSpeed to 200.");
				car.setMaxSpeed(200);
			}
		}
		return bean;
	}
}	

注册接口

 上述这写接口除了在Car.java中直接定义的接口其他的接口都需要注册加载。首先我们在beans.xml中注册myInit和myDestroy方法。代码更改如下:

	<bean id="car1" class="com.smart.Car"
	init-method="myInit"
	destroy-method="myDestroy"
	p:brand="红旗CA72"
	p:color="黑色"
	p:maxSpeed="200"
	/>
	</beans>

 下面让容器装载配置文件,然后分别注册上面所提供的两个后处理器。在com.smart.beanfactory下创建BeanLifeCycle.java文件,代码如下:

package com.smart.beanfactory;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import com.smart.Car;
public class BeanLifeCycle{
	private static void LifeCycleInBeanFactory() {
		//装载配置文件并启动容器
		Resource res = new ClassPathResource("com/smart/beanfactory/beans.xml");
		BeanFactory bf = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((DefaultListableBeanFactory)bf);
		reader.loadBeanDefinitions(res);
		
		//向容器注册MyBeanPostProcessor后处理器
		((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
		
		//向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
		((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());
		
		//第一次从容器中获取car,将出发容器实例化Bean,将引发生命周期方法的调用
		Car car1 = (Car)bf.getBean("car1");
		car1.introduce();
		car1.setColor("红色");
		
		//第二次从容器中获取Car,直接从缓存池中获取
		Car car2 = (Car)bf.getBean("car1");
		
		//查看car1和car2是否指向同一引用
		System.out.println("car1 == car2:" + (car1==car2));
		
		//关闭容器
		((DefaultListableBeanFactory)bf).destroySingletons();
	}
	
	public static void main(String[] args) {
		LifeCycleInBeanFactory();
	}
}

 这里需要注意的是多个后处理器的调用顺序和注册顺序无关,必须通过实现org.springframework.core.Ordered接口来确定调用顺序。
 运行该代码即可基本了解调用的过程。

ApplicationContext中Bean的生命周期

 书中给出的生命周期图如下:
在这里插入图片描述
 可以看到在Application只是多了几个步骤:

  1. 如果Bean实现了org.springframework.context.ApplicationContextAware接口则会增加一个调用该接口方法setApplicationContext()的步骤
  2. 如果在配置文件中申明了后处理接口BeanFactoryPostProcessor的实现类,则应用上下文在装载配置文件之后,初始化实例之前将调用BeanFactoryPostProcessor对配置信息进行加工处理。

 除此之外,ApplicationContext会利用java的反射机制自动识别出配置文件中定义的BeanPostProcessor等后处理器并注册到上下文中,而不像BeanFactory需要手工调用addBeanPostProcessor()进行注册。

实例

 假设我们希望对配置文件中car1的brand配置属性进行调整。在com.smart.context创建一个MyBeanFactoryPostProcessor.java,代码如下:

package com.smart.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 com.smart.Car;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
	//对car的brand配置信息进行加工操作
	public void postProcessBeanFactory(ConfigurableListableBeanFactory bf)
		throws BeansException{
		BeanDefinition bd = bf.getBeanDefinition("car1");
		bd.getPropertyValues().addPropertyValue("brand", "奇瑞QQ");
		System.out.println("调用BeanFactoryPostProcessor.postProcessBean Factory()");
		
	}
}

 ApplicationContext在启动时,将首先为配置文件中的每一个<bean>生成一个BeanDefinition对象(<bean>在spring容器中的内部表示)而后我们就有机会对其进行修改。
 接下来对beans.xml修改:

<bean id="car1" class="com.smart.Car"
	init-method="myInit"
	destroy-method="myDestroy"
	p:brand="红旗CA72"
	p:color="黑色"
	p:maxSpeed="200"
	/>
	<bean id = "myBeanFactoryPostProcessor"
		class = "com.smart.context.MyBeanFactoryPostProcessor"/>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值