Spring__Bean的生命周期

这篇可以说是对前面那些接口的总结,总结完后,发现其实就是bean生命周期用的这些接口:
BeanFactoryPostProcessor
InstantiationAwareBeanPostProcessor
Aware
BeanPostProcessor
@PostConstruct与@PreDestroy
InitializingBean与DisposableBean
init-method与destroy-method

在IoC容器启动之后,并不会马上就实例化相应的bean,此时容器仅仅拥有所有对象的BeanDefinition(BeanDefinition:是容器依赖某些工具加载的XML配置信息进行解析和分析,并将分析后的信息编组为相应的BeanDefinition)。只有当getBean()调用时才是有可能触发Bean实例化阶段的活动


可以简述为以下九步

实例化bean对象(通过构造方法或者工厂方法)
设置对象属性(setter等)(依赖注入)
如果Bean实现了BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。(和下面的一条均属于检查Aware接口)
如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身
将Bean实例传递给Bean的前置处理器的postProcessBeforeInitialization(Object bean, String beanname)方法
调用Bean的初始化方法
将Bean实例传递给Bean的后置处理器的postProcessAfterInitialization(Object bean, String beanname)方法
使用Bean
容器关闭之前,调用Bean的销毁方法

较详细总结:

1、如果实现了BeanFactoryPostProcessor接口,那么在容器启动的时候,该接口中的postProcessBeanFactory方法可以修改Bean中元数据中的信息。
该方法是在实例化对象之前执行。

2、如果实现了InstantiationAwareBeanPostProcessor接口,那么在实例化Bean对象之前会调用postProcessBeforeInstantiation方法,该方法如果返回的不为null则会直接调用postProcessAfterInitialization方法,而跳过了Bean实例化后及初始化前的相关方法,如果返回null则正常流程,postProcessAfterInstantiation在实例化成功后执行,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true, postProcessPropertyValues就会被执行,postProcessPropertyValues用来修改属性,在初始化方法之前执行。

3、如果实现了Aware相关的结果,那么相关的set方法会在初始化之前执行。

4、如果实现了BeanPostProcessor接口,那么该接口的方法会在实例化后的初始化方法前后执行。

5、如果指定了@PostConstruct则在初始化的时候会执行标注的方法。

6、如果实现了InitializingBean接口则在初始化的时候执行afterPropertiesSet。

7、如果指定了init-method属性则在初始化的时候会执行指定的方法。

8、到此对象创建完成。

9、当对象需要销毁的时候。

10、如果指定了@PreDestroy注解则会执行标注的方法。

11、如果实现了DisposableBean接口会执行destroy方法。

12、如果指定了destroy-method属性则会执行指定的方法。

执行顺序:(非一定流程)

对象创建:

1、如果实现了BeanFactoryPostProcessor接口在容器启动的时,bean实例化前,可以获取bean的相关定义信息,可以修改bean的元数据  --
2、如果实现了InstantiationAwareBeanPostProcessor接口,它的postProcessBeforeInstantiation方法会在bean实例化之前被调用,返回值不为null则跳过实例化后与初始化前的执行方法,直接执行BeanPostProcessor接口中的postProcessAfterInitialization方法, postProcessAfterInitialization方法是在初始化后执行的;如果返回值为null,那么会按正常流程走,不跳过流程;---

3、无参构造实例化对象 -

4、依赖注入 -

5、如果指定了@PostConstruct则在初始化的时候会执行标注的方法。--

6、如果实现了InitializingBean接口则在初始化的时候执行afterPropertiesSet。---

7、如果指定了init-method属性则在初始化的时候会执行指定的方法。---

8、到此对象创建完成。

对象销毁:

9、如果指定了@PreDestroy注解则会执行标注的方法。--->

10、如果实现了DisposableBean接口会执行destroy方法。-

11、如果指定了destroy-method属性则会执行指定的方法。-

ZslBeanFactoryPostProcessor 实现了BeanFactoryPostProcessor:

package com.pojo;

import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class ZslBeanFactoryPostProcessor implements BeanFactoryPostProcessor{

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("进入了BeanFactoryPostProcessor中的postProcessBeanFactory方法开始执行");
		
		/**
		 * 获取在IOC容器中注册了的bean的名称
		 */
		String[] definitionNames = beanFactory.getBeanDefinitionNames();
		for (String dname : definitionNames) {
			System.out.println("dname:"+dname);
			if (dname.equals("studentA")) {// 找到我们需要的bean的名称,与配置文件里的id或者name一致
				/**
				 *Spring容器启动的过程中,会将Bean解析成Spring内部的BeanDefinition结构
				 *其实就是将Bean的定义信息存储到这个BeanDefinition相应的属性中,
				 *后面对Bean的操作就直接对BeanDefinition进行,
				 *例如拿到这个BeanDefinition后,可以根据里面的类名、构造函数、构造函数参数,使用反射进行对象创建。
				 *BeanDefinition是一个接口,是一个抽象的定义,实际使用的是其实现类,
				 *如 ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。
				 */
				BeanDefinition beanDefinition = beanFactory.getBeanDefinition(dname);
				
				/**
				 * 通过BeanDefinition获取我们的配置文件,这里是applicationContext.xml
				 */
				MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
				
				/**
				 * 获取到了xml配置文件后,可以修改其中一项
				 */
				if (propertyValues.contains("stuId")) {
					Object value = propertyValues.get("stuId");
					System.out.println("修改前stuId:"+value);
					propertyValues.addPropertyValue("stuId", "zsl66");
					Object value1 = propertyValues.get("stuId");
					System.out.println("修改后stuId:"+value1);
					System.out.println("修改了配置文件里的studentA的stuId");
				}
				
			}
		}
		System.out.println("postProcessBeanFactory执行结束");
	}

}

StuBeanPostProcessor实现了BeanPostProcessor

package com.pojo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;

public class StuBeanPostProcessor implements BeanPostProcessor ,Ordered{
	/**
	 * 实例化、依赖注入完毕,
     * 在调用显示的初始化之前完成一些定制的初始化任务
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessBeforeInitialization 实例化、依赖注入完毕,初始化之前执行");
		System.out.println("postProcessBeforeInitialization中bean:"+bean+",beanName:"+beanName);
		return bean;
	}

	/**
	 * 实例化、依赖注入、初始化完毕时执行
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("postProcessAfterInitialization初始化完毕时执行");
		System.out.println("postProcessAfterInitialization中bean:"+bean+",beanName:"+beanName);
		return bean;
	}

	/**
	 * 多个BeanPostProcessor时,可以指定执行顺序
	 * 默认为0优先级最高,值越小,越靠前,优先级越大
	 */
	@Override
	public int getOrder() {
		// TODO Auto-generated method stub
		return 3;
	}
}

ZslInstantiationAwareBeanPostProcessor实现了InstantiationAwareBeanPostProcessor

package com.pojo;

import java.beans.PropertyDescriptor;

import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;

public class ZslInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor{

	/**
	 * BeanPostProcessor接口的方法,在实例化后,依赖注入后,初始化前执行
	 */
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("InstantiationAwareBeanPostProcesso中postProcessBeforeInitialization初始化前执行");
		return bean;
	}
	
	/**
	 * BeanPostProcessor接口的方法,在实例化后,依赖注入后,初始化完成后执行
	 */
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("InstantiationAwareBeanPostProcesso中postProcessAfterInitialization初始化完成后执行");
		return bean;
	}

	/**
	 * InstantiationAwareBeanPostProcessor接口的方法,实例化前执行
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("InstantiationAwareBeanPostProcesso中postProcessBeforeInstantiation实例化前执行");
		return null;
	}

	/**
	 * InstantiationAwareBeanPostProcessor接口的方法,实例化完成后,依赖注入之前执行
	 */
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("InstantiationAwareBeanPostProcesso中postProcessAfterInstantiation实例化完成后,依赖注入之前执行");
		return true;
	}

	/**
	 * 如果postProcessAfterInstantiation返回为false则不用执行
	 * 在postProcessPropertyValues中可以对bean的属性进行修改
	 */
	@Override
	public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,
			String beanName) throws BeansException {
		// TODO Auto-generated method stub
		System.out.println("InstantiationAwareBeanPostProcesso中postProcessPropertyValues对bean的属性进行修改");
		return pvs;
	}

}

StudentA目标类

package com.pojo;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class StudentA implements InitializingBean,DisposableBean{
	private String name;
	private String stuId;
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
		System.out.println("设值注入Name:"+name);
	}
	
 	public String getStuId() {
		return stuId;
	}
 	
	public void setStuId(String stuId) {
		this.stuId = stuId;
		System.out.println("设值注入stuId:"+stuId);
	}
	
	public StudentA(String name, String stuId) {
		super();
		this.name = name;
		this.stuId = stuId;
	}
	
	public StudentA() {
		super();
		// TODO Auto-generated constructor stub
		System.out.println("通过无参构造...StudentA实例化");
	}
	
	@Override
	public String toString() {
		return "StudentA [name=" + name + ", stuId=" + stuId + "]";
	}
	
	/**
	 * 重写DisposableBean接口里的方法
	 * 在销毁前回调
	 */
	@Override
	public void destroy() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("DisposableBean接口的destroy()");
	}
	
	/**
	 * 重写InitializingBean接口里的方法
	 * 在实例化并设值注入后初始化回调
	 */
	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("InitializingBean接口的afterPropertiesSet()");
	}
	
	/**
	 * 自定义初始化后回调
	 * 对应着bean里的init-method="start"
	 */
	public void start() {
		// TODO Auto-generated method stub
		System.err.println("自定义初始化回调...init-method=\"start\"");
	}
	
	/**
	 * 自定义销毁前回调
	 * 对应着bean里的destroy-method="end"
	 */
	public void end() {
		// TODO Auto-generated method stub
		System.out.println("自定义销毁回调...destroy-method=\"end\"");
	}
	
	/**
	 * 通过@PreDestroy注解
	 * 初始化后回调方法
	 */
	@PostConstruct
	public void postConstruct(){
		System.out.println("初始化后回调方法...@postConstruct注解");
	}
	
	
	/**
	 * 通过@PreDestroy注解
	 * 销毁前回调方法
	 */
	@PreDestroy
	public  void preDestory(){
		System.out.println("销毁前回调方法...@preDestory注解");
	}

	
	
}

ApplicationContext.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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
		
		
		<!-- 如果想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor -->
	    <context:annotation-config/> 
		
		<!-- 注册studentA对象 -->
	 	<bean class="com.pojo.StudentA" id="studentA" init-method="start" destroy-method="end">
			<!-- 设值注入 -->
			<property name="name" value="zsl"/>
			<property name="stuId" value="zsl33"/>
		</bean>  
<!-- 注册StuBeanPostProcessor,它实现了BeanPostProcessor -->
		  <bean class="com.pojo.StuBeanPostProcessor"/>
<!-- 注册ZslBeanFactoryPostProcessor,实现了BeanFactoryPostProcessor接口 -->
		  <bean class="com.pojo.ZslBeanFactoryPostProcessor" />  
		
		<!-- 注册ZslInstantiationAwareBeanPostProcessor,实现了InstantiationAwareBeanPostProcessor接口 -->
		<bean class="com.pojo.ZslInstantiationAwareBeanPostProcessor"/>	
</beans>

测试:

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.pojo.Cat;
import com.pojo.Dog;
import com.pojo.StudentA;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanNameAware;
public class Test {
	@SuppressWarnings("resource")//去警告,问题不大不要慌
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = 
				new ClassPathXmlApplicationContext("applicationContext.xml");
		
		StudentA bean = (StudentA) applicationContext.getBean("studentA");
	System.out.println(bean);
		
		/**
		 * 在非web环境下需要手动关闭IOC容器,则需调用registerShutdownHook()方法
		 * 而web环境下已有相应的配置进行关闭IOC容器
		 */
		applicationContext.registerShutdownHook();
	}
} 

结果:

借鉴于大佬:

https://dpb-bobokaoya-sm.blog.csdn.net/article/details/88143169
https://blog.csdn.net/w_linux/article/details/80086950

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

偷偷学习被我发现

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值