spring (10)Spring的生命周期

490 阅读10分钟

目录

spring的生命周期与多个接口有关,整个spring的生命周期是由spring进行管理的.

1.bean对象的初始化方法与销毁方法

bean对象的初始化方法:在bean对象的实例化(默认构造函数),初始化(set方法)执行之后,spring会显示调用的方法.主要有一下三种申明方法:

  • 标签中添加 init-method
<bean class="com.qunar.spring入门.pojo.User3" id="user3" init-method="start">
  • 在bean定义的方法上加上@PostConstruct注解
public class User2{
    private Integer userId;
   
    public User2(){
        System.out.println("构造器");
    }
    
    @PostConstruct
    void printInfo() {
        System.out.println("user2");
    }

  • 实现InitializingBean接口,重写afterPropertiesSet()方法
public class User2 implements InitializingBean{
    private Integer userId;

    public User2(){
        System.out.println("构造器");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("after");
    }
}

执行顺序为: 构造方法>>@postConstruct 或者:构造方法>>afterPropertiesSet()>>init-method.

bean对象的销毁方法:spring容器在执行销毁方法之前的回调方法,销毁回调方法也有三种:

  • 标签中只用destory-method指定回调方法
	<bean class="com.dpb.pojo.User" id="user" init-method="start" destroy-method="end">
  • 通过实现DisposableBean接口,重写destory方法
public class AnotherExampleBean implements DisposableBean {
 
    public void destroy() {
        // do some destruction work (like releasing pooled connections)
    }
}
  • @PreDestory注解
	@PreDestroy
	public  void preDestory(){
		System.out.println("--preDestory---");
	}

执行顺序: @PreDestory容器销毁 或者:destory()>>destory-method>>容器销毁.

2.Aware接口

实现aware接口,bean可以访问spring容器,*这些aware方法会在对象实例化之后,为bean注入属性之后,自定义的初始化方法之前执行

2.2常见的Aware接口

2.1ApplicationContextAware
void setApplicationContext(ApplicationContext applicationContext)

2.2BeanClassLoaderAware
void setBeanClassLoader(ClassLoader classLoader);

2.3BeanFactoryAware
void setBeanFactory(BeanFactory beanFactory)

2.4BeanNameAware
void setBeanName(String name);

通过Aware接口,可以在bean加载进spring容器时,感知spring容器的信息,将这些信息设置进bean对象之中

**
 * 实现了
 * 	ApplicationContextAware
 *  BeanClassLoaderAware
 *  BeanFactoryAware
 *  BeanNameAware
 *  接口
 * @author dengp
 *
 */
public class User implements ApplicationContextAware,BeanClassLoaderAware,BeanFactoryAware,BeanNameAware{

	private int id;
	
	private String name;
	// 保存感知的信息
	private String beanName;
	// 保存感知的信息
	private BeanFactory beanFactory;
	// 保存感知的信息
	private ApplicationContext ac;
	// 保存感知的信息
	private ClassLoader classLoader;
	
	public BeanFactory getBeanFactory() {
		return beanFactory;
	}

	public ApplicationContext getAc() {
		return ac;
	}

	public ClassLoader getClassLoader() {
		return classLoader;
	}

	public User(){
		System.out.println("User 被实例化");
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getBeanName() {
		return beanName;
	}
	
	/**
	 * 自定义的初始化方法
	 */
	public void start(){
		System.out.println("User 中自定义的初始化方法");
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", beanName=" + beanName + "]";
	}

	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		System.out.println(">>> setBeanClassLoader");
		this.classLoader = classLoader;
	}

	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		System.out.println(">>> setApplicationContext");
		this.ac = applicationContext;
	}

	@Override
	public void setBeanName(String name) {
		System.out.println(">>> setBeanName");
		this.beanName = name;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		System.out.println(">>> setBeanFactory");
		this.beanFactory = beanFactory;
	}
}

测试类:

@Test
public void test1() {
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = ac.getBean(User.class);
	System.out.println("beanFactory:"+user.getBeanFactory());
	System.out.println("beanName:"+user.getBeanName());
	System.out.println("applicationContext:"+user.getAc());
	System.out.println("classLoader:"+user.getClassLoader());
	System.out.println(user);
}

输出结果:


User 被实例化
>>> setBeanName
>>> setBeanClassLoader
>>> setBeanFactory
>>> setApplicationContext
User 中自定义的初始化方法
beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@4520ebad: defining beans [user]; root of factory hierarchy
beanName:user
applicationContext:org.springframework.context.support.ClassPathXmlApplicationContext@311d617d: startup date [Sun Mar 03 22:43:08 CST 2019]; root of context hierarchy
classLoader:sun.misc.Launcher$AppClassLoader@4aa298b7
User [id=0, name=波波烤鸭, beanName=user]

3.BeanPostProcessor接口

也叫做后置处理器,通过beanPostProcessor可以在bean的实例化和依赖注入之后,显示调用自定义初始化方法的前后,进行相关方法的调用或者自定义逻辑的处理 BeanProcessor接口的源码

public interface BeanPostProcessor {
	//在自定义的init方法前执行
	Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    //在自定义的init方法后执行
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

-(一)BeanPostProcessor的使用

/**
 * 自定义BeanPostProcessor实现类
 * BeanPostProcessor接口的作用是:
 * 	 我们可以通过该接口中的方法在bean实例化、配置以及其他初始化方法前后添加一些我们自己的逻辑
*/
public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     * 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
     * 注意:方法返回值不能为null
     * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
     * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("before--实例化的bean对象:"+bean+"\t"+beanName);
        // 可以根据beanName不同执行不同的处理操作
        return bean;
    }

    /**
     * 实例化、依赖注入、初始化完毕时执行
     * 注意:方法返回值不能为null
     * 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象
     * 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("after...实例化的bean对象:"+bean+"\t"+beanName);
        // 可以根据beanName不同执行不同的处理操作
        return bean;
    }
}
public class User3 {

    private int id;

    private String name;

    private String beanName;

    public User3(){
        System.out.println("User 被实例化");
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("设置:"+name);
        this.name = name;
    }

    public String getBeanName() {
        return beanName;
    }

    public void setBeanName(String beanName) {
        this.beanName = beanName;
    }
    /**
     * 自定义的初始化方法
     */
    public void start(){
        System.out.println("User 中自定义的初始化方法");
    }

    @Override
    public String toString() {
        return "User3{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", beanName='" + beanName + '\'' +
                '}';
    }
}

xml的配置,将PostPostPrecessor添加进容器即可

 <bean class="com.qunar.spring入门.pojo.User3" id="user3" init-method="start">
        <property name="name" value="波波烤鸭" />
    </bean>

    <!-- 注册处理器 -->
    <bean class="com.qunar.spring入门.pojo.MyBeanPostProcessor"></bean>

执行结果:

ser 被实例化
设置:波波烤鸭
before--实例化的bean对象:User3{id=0, name='波波烤鸭', beanName='null'}	user3
User 中自定义的初始化方法
after...实例化的bean对象:User3{id=0, name='波波烤鸭', beanName='null'}	user3
User3{id=0, name='波波烤鸭', beanName='null'}

也可以设置多个BeanPostProcessor,会默认按照申明的顺序进行调用,也可以实现Ordered接口,实现 getOrder() 方法指定顺序,在Spring机制中可以指定后置处理器调用顺序,通过让BeanPostProcessor接口实现类实现Ordered接口getOrder方法,该方法返回一整数,默认值为 0,优先级最高,值越大优先级越低

public class MyBeanPostProcessor implements BeanPostProcessor,Ordered{
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    	return bean;
	}

	@Override
	public int getOrder() {
		// TODO Auto-generated method stub
		return 10;
	}
}

4.InstantiationAwareBeanPostProcessor接口

InstantiationAwareBeanPostProcessor接口是BeanPostProcesso的子接口,主要的作用是感知bean的实例化,在bean的实例化前后,对象的属性注入之前进行相关的操作;

接口源码

package org.springframework.beans.factory.config;
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

	Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

	boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

	PropertyValues postProcessPropertyValues(
			PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}

从源码中我们可以获知的信息是该接口除了具有父接口中的两个方法以外还自己额外定义了三个方法。所以该接口一共定义了5个方法,这5个方法的作用分别是

方法描述
postProcessBeforeInitializationBeanPostProcessor接口中的方法,在Bean的自定义初始化方法之前执行
postProcessAfterInitializationBeanPostProcessor接口中的方法在Bean的自定义初始化方法执行完成之后执行
postProcessBeforeInstantiation自身方法,是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
postProcessAfterInstantiation在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
postProcessPropertyValues对属性值进行修改,如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改

示例:

/**
 * 自定义处理器
 * @author dengp
 *
 */
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{

	/**
	 * BeanPostProcessor接口中的方法
	 * 在Bean的自定义初始化方法之前执行
	 * Bean对象已经存在了
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println(">>postProcessBeforeInitialization");
		return bean;
	}

	/**
	 * BeanPostProcessor接口中的方法
	 * 在Bean的自定义初始化方法执行完成之后执行
	 * Bean对象已经存在了
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("<<postProcessAfterInitialization");
		return bean;
	}

	/**
	 * InstantiationAwareBeanPostProcessor中自定义的方法
	 * 在方法实例化之前执行  Bean对象还没有
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		System.out.println("--->postProcessBeforeInstantiation");
		return null;
	}

	/**
	 * InstantiationAwareBeanPostProcessor中自定义的方法
	 * 在方法实例化之后执行  Bean对象已经创建出来了
	 */
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		System.out.println("<---postProcessAfterInstantiation");
		return true;
	}

	/**
	 * InstantiationAwareBeanPostProcessor中自定义的方法
	 * 可以用来修改Bean中属性的内容
	 */
	@Override
	public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
			String beanName) throws BeansException {
		System.out.println("<---postProcessPropertyValues--->");
		return pvs;
	}
}

目标对象

public class User {

	private int id;
	
	private String name;
	
	private String beanName;
	
	public User(){
		System.out.println("User 被实例化");
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		System.out.println("设置:"+name);
		this.name = name;
	}

	public String getBeanName() {
		return beanName;
	}

	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}
	public void start(){
		System.out.println("自定义初始化的方法....");
	}
	
	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", beanName=" + beanName + "]";
	}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	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 class="com.dpb.pojo.User" id="user" init-method="start">
		<property name="name" value="波波烤鸭"></property>
	</bean>
	
	<!-- 注册InstantiationAwareBeanPostProcessor对象 -->
	<bean class="com.dpb.processor.MyInstantiationAwareBeanPostProcessor"></bean>
</beans>

测试

@Test
public void test1() {
	ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = ac.getBean(User.class);
	System.out.println(user);
	// 关闭销毁
	ac.registerShutdownHook();
}

测试结果:

--->postProcessBeforeInstantiation
User 被实例化
<---postProcessAfterInstantiation
<---postProcessPropertyValues--->
设置:波波烤鸭
>>postProcessBeforeInitialization
自定义初始化的方法....
<<postProcessAfterInitialization
User [id=0, name=波波烤鸭, beanName=null]

说明:

  1. 如果postProcessBeforeInstantiation返回不为null;说明修改了bean对象;中间的实例化之后 和 初始化之前都不执行,直接执行postProcessAfterInitialization方法; 2.postProcessAfterInstantiation返回值要注意,因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素;如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返true,postProcessPropertyValues就会被执行 3.在populateBean方法中我们已经看到了postProcessPropertyValues执行的位置

postPorcessPropertyValues执行的示例

/**
 * InstantiationAwareBeanPostProcessor中自定义的方法 可以用来修改Bean中属性的内容
 */
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
		String beanName) throws BeansException {
	System.out.println("<---postProcessPropertyValues--->");
	if(bean instanceof User){
		PropertyValue value = pvs.getPropertyValue("name");
		System.out.println("修改前name的值是:"+value.getValue());
		value.setConvertedValue("bobo");
	}
	return pvs;
}

5.BeanFactoryPostProcessor接口

BeanactoryPostProcessor接口允许在spring容器实例化任何bean之前,对bean的定义信息进行更改,可以定义多个BeanFactoryPostProcessor类,通过Order接口的返回值确定执行的顺序.

示例 实现接口

/**
 * 自定义BeanFactoryPostProcessor
 * 
 * @author dengp
 *
 */
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

	/**
	 * 本方法在Bean对象实例化之前执行,
	 * 通过beanFactory可以获取bean的定义信息,
	 * 并可以修改bean的定义信息。这点是和BeanPostProcessor最大区别
	 */
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		
		System.out.println(">> BeanFactoryPostProcessor 开始执行了");
		String[] names = beanFactory.getBeanDefinitionNames();
		for (String name : names) {
			if("user".equals(name)){
				
				BeanDefinition beanDefinition = beanFactory.getBeanDefinition(name);
				MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
				// MutablePropertyValues如果设置了相关属性,可以修改,如果没有设置则可以添加相关属性信息
				if(propertyValues.contains("name")){
					propertyValues.addPropertyValue("name", "bobo");
					System.out.println("修改了属性信息");
				}
			}
		}
		System.out.println(">> BeanFactoryPostProcessor 执行结束");
	}
}

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	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 class="com.dpb.pojo.User" id="user" init-method="start">
		<property name="name" value="波波烤鸭"></property>
	</bean>
	
	<!-- 注册处理器 -->
	<bean class="com.dpb.processor.MyBeanPostProcessor"/>
	<!-- 注册BeanFactoryPostProcessor -->
	<bean class="com.dpb.factoryprocessor.MyBeanFactoryPostProcessor"></bean>
</beans>

主程序

@Test
public void test1() {
	ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	User user = ac.getBean(User.class);
	System.out.println(user);
}

输出结果

>> BeanFactoryPostProcessor 开始执行了
修改了属性信息
>> BeanFactoryPostProcessor 执行结束
User 被实例化
设置:bobo
A before--实例化的bean对象:User [id=0, name=bobo, beanName=null]	user
User 中自定义的初始化方法
A after...实例化的bean对象:User [id=0, name=bobo, beanName=null]	user
User [id=0, name=bobo, beanName=null]

6.总结

image.png

示例:

public class 测试spring的生命周期对象 implements InitializingBean, DisposableBean , BeanNameAware {

    //自身属性值
    private int id;
    private String name;
    private String beanName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("属性注入");
        this.name = name;
    }

    public 测试spring的生命周期对象(){
        System.out.println("实例化");
    }

    @PostConstruct
    public void start1(){
        System.out.println("执行postConstruct");
    }

    public void start2() {
        System.out.println("执行init-method方法");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行afterPropertiesSet");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("执行destroy");
    }

    public void end2() {
        System.out.println("执行destory-method");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("执行aware方法");
        this.beanName=name;
    }
}

InstantiationAwareBeanPostProcessor接口实现类

public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        System.out.println("执行postProcessBeforeInstantiation方法");
        //return new User();
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        System.out.println("执行postProcessAfterInstantiation");
        return true;
    }

    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        System.out.println("执行postProcessPropertyValues");
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行postProcessBeforeInitialization");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("执行postProcessAfterInitialization");
        return bean;
    }
}

配置文件

    <!-- 注册处理器 -->
    <bean id="springbean" class="com.qunar.spring入门.pojo.测试spring的生命周期对象" init-method="start2" destroy-method="end2">
        <property name="name" value="第一个名称"></property>
    </bean>
    <!--注册-->
    <bean id="myBeanFactoryPostProcessor" class="com.qunar.spring入门.pojo.MyBeanFactoryPostProcessor"></bean>
    <bean id="myBeanFactoryPostProcessor2" class="com.qunar.spring入门.pojo.MyBeanFactoryPostProcessor2"></bean>

    <bean id="myInstantiationAwareBeanPostProcessor" class="com.qunar.spring入门.pojo.MyInstantiationAwareBeanPostProcessor"></bean>

测试类

public class 测试spring的生命周期 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring的生命周期.xml");
        测试spring的生命周期对象 b= (测试spring的生命周期对象)applicationContext.getBean("springbean");
        System.out.println(b.getName());
        applicationContext.close();
    }
}

输出结果:

执行postProcessBeanFactory方法
修改了属性值
执行postProcessBeanFactory2方法
又修改了属性值
执行postProcessBeforeInstantiation方法
实例化
执行postProcessAfterInstantiation
执行postProcessPropertyValues
属性注入
执行aware方法
执行postProcessBeforeInitialization
执行afterPropertiesSet
执行init-method方法
执行postProcessAfterInitialization
第三个名字
执行destroy
执行destory-method

Process finished with exit code 0