Spring中的Bean的生命周期
1. 什么是Spring中Bean的生命周期
Spring最大的特点就是面向Bean(BOP)编程,Spring所管理的Bean是一个POJO,即简单的JavaBean(不需要实现任何规范的Bean)。Spring提供了很多方法可以对所管理的Bean对象进行功能增强,其中就包含了对生命周期的控制。
2. Bean创建前的准备阶段
在Bean被Spring创建之前,首先会实例化IoC容器,找到所有被Spring管理的Bean的配置信息。同时还会实例化BeanFactoryPostProcessor、InstantiationAwareBeanPostProcessor、BeanPostProcessor等处理器。
接口 | 说明 |
---|---|
BeanFactoryPostProcessor | 该接口只有一个BeanFactoryPostProcessor()方法,在BeanFactory初始化之后可以对Bean的元数据进行修改。此时Bean还没有被实例化。 |
InstantiationAwareBeanPostProcessor | 该接口的实现类在准备阶段只会进行实例化,并不会调用任何方法。 |
BeanPostProcessor | 该接口的实现类在准备阶段只会进行实例化,并不会调用任何方法。 |
2.1 代码演示
package com.wxw.processor.ioc;
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;
public class WxwBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public WxwBeanFactoryPostProcessor() {
System.out.println("调用【BeanFactoryPostProcessor】构造方法!!!");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("调用【BeanFactoryPostProcessor】类的postProcessBeanFactory方法!!!");
// 在这里可以修改Bean的元数据
BeanDefinition userBean = configurableListableBeanFactory.getBeanDefinition("userBean");
userBean.getPropertyValues().addPropertyValue("age","28");
}
}
package com.wxw.processor.instantiation;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
public class WxwInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public WxwInstantiationAwareBeanPostProcessor() {
System.out.println("调用【InstantiationAwareBeanPostProcessor】构造方法!!!");
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("调用【InstantiationAwareBeanPostProcessor】的Before方法!!!");
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("调用【InstantiationAwareBeanPostProcessor】的After方法!!!");
return false;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
return null;
}
}
package com.wxw.processor.initialize;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class WxwBeanPostProcessor implements BeanPostProcessor {
public WxwBeanPostProcessor(){
System.out.println("调用【BeanPostProcessor】构造方法!!!");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用【BeanPostProcessor】的【Before】方法!!!");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用【BeanPostProcessor】的【After】方法!!!");
return null;
}
}
package com.wxw.test;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestClass {
@Test
public void test1(){
System.out.println("=====================IoC容器初始化begin=========================");
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
System.out.println("=====================IoC容器初始化end=========================");
}
}
运行结果如下:
=====================IoC容器初始化begin=========================
调用【BeanFactoryPostProcessor】构造方法!!!
调用【BeanFactoryPostProcessor】类的postProcessBeanFactory方法!!!
调用【InstantiationAwareBeanPostProcessor】构造方法!!!
调用【BeanPostProcessor】构造方法!!!
=====================IoC容器初始化end=========================
2.2 时序图
3. Bean实例化阶段
Spring中的Bean在实例化阶段会被InstantiationAwareBeanPostProcessor处理器的相关方法进行处理。
接口 | 说明 |
---|---|
InstantiationAwareBeanPostProcessor | 该接口有3个方法: 1. postProcessBeforeInstantiation():该方法会在Bean实例化之前调用,如果该方法返回的是非空对象,则会跳过Spring创建Bean的过程(包括依赖注入、初始化等操作),直接执行BeanPostProcessor的后置处理器,然后返回这个对象。如果该方法返回为空,则执行Spring创建Bean的正常流程。 2. postProcessAfterInstantiation():该方法会在Bean实例化之后,依赖注入之前调用,如果该方法返回false,则直接退出populateBean()方法(依赖注入),使当前Bean依赖注入步骤短路。如果该方法返回true,则执行正常流程。 3. postProcessProperties():该方法在After方法返回true后执行,可以在Spring给Bean属性值设置之前,对该Bean的属性进行处理。 |
3.1 代码演示
package com.wxw.processor.instantiation;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import java.lang.reflect.Constructor;
public class WxwInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
public WxwInstantiationAwareBeanPostProcessor() {
System.out.println("调用【InstantiationAwareBeanPostProcessor】构造方法!!!");
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("调用【InstantiationAwareBeanPostProcessor】的Before方法!!!");
Object obj = null;
try {
Constructor<?> constructor = beanClass.getConstructor(String.class, Integer.class);
obj = constructor.newInstance("wxw",20);
} catch (Exception e) {
e.printStackTrace();
}
return obj;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("调用【InstantiationAwareBeanPostProcessor】的After方法!!!");
return false;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("调用【InstantiationAwareBeanPostProcessor】的postProcessProperties方法!!!");
return pvs;
}
}
package com.wxw.pojo;
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
@Data
public class UserBean implements InitializingBean {
private String name;
private Integer age;
public UserBean() {
System.out.println("调用【UserBean】的构造方法!!!");
}
public UserBean(String name, Integer age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
System.out.println("调用【UserBean】的【setName】方法!!!");
this.name = name;
}
public void setAge(Integer age) {
System.out.println("调用【UserBean】的【setAge】方法!!!");
this.age = age;
}
@Override
public String toString() {
return "UserBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【UserBean】的【init】方法执行!!!");
}
}
运行结果如下:
=====================IoC容器初始化begin=========================
调用【BeanFactoryPostProcessor】构造方法!!!
调用【BeanFactoryPostProcessor】类的postProcessBeanFactory方法!!!
调用【InstantiationAwareBeanPostProcessor】构造方法!!!
调用【BeanPostProcessor】构造方法!!!
=====================IoC容器初始化end=========================
调用【InstantiationAwareBeanPostProcessor】的Before方法!!!
调用【BeanPostProcessor】的【After】方法!!!
3.2 时序图
4. Bean初始化阶段
在Bean初始化阶段会执行Aware接口实现类的相关方法、BeanPostProcessor处理相关的方法、InitializingBean接口的setBeanFactory方法、xml中配置的init-method方法。
接口 | 说明 |
---|---|
Aware | 实现该接口的类,会让该类感知到某些属性,比如:BeanFactoryAware、BeanNameAware等等 |
BeanPostProcessor | 该接口有2个方法: 1. postProcessBeforeInitialization:在Bean初始化回调函数之前执行 2. postProcessAfterInitialization:在Bean初始化回调函数之后执行 |
InitializingBean | setBeanFactory方法:Bean的初始化回调函数 |
init-method配置的方法 | 与InitializingBean接口的方法一样,初始化回调函数 |
4.1 代码演示
UserBean类:
package com.wxw.pojo;
import lombok.Data;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
@Data
public class UserBean implements InitializingBean, BeanFactoryAware {
private String name;
private Integer age;
private BeanFactory beanFactory;
public UserBean() {
System.out.println("调用【UserBean】的构造方法!!!");
}
public UserBean(String name, Integer age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
System.out.println("调用【UserBean】的【setName】方法!!!");
this.name = name;
}
public void setAge(Integer age) {
System.out.println("调用【UserBean】的【setAge】方法!!!");
this.age = age;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用【BeanFactoryAware】的【setBeanFactory】方法!!!");
this.beanFactory = beanFactory;
}
@Override
public String toString() {
return "UserBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean】的【init】方法执行!!!");
}
public void init(){
System.out.println("【init-method】配置的【init】方法执行!!!");
}
}
spring-config.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userBean" class="com.wxw.pojo.UserBean"
lazy-init="true"
init-method="init"
scope="singleton">
<property name="name" value="Wxw"/>
<property name="age" value="18"/>
</bean>
<bean id="wxwBeanFactoryPostProcessor" class="com.wxw.processor.ioc.WxwBeanFactoryPostProcessor"></bean>
<bean id="wxwInstantiationAwareBeanPostProcessor" class="com.wxw.processor.instantiation.WxwInstantiationAwareBeanPostProcessor"></bean>
<bean id="wxwBeanPostProcessor" class="com.wxw.processor.initialize.WxwBeanPostProcessor"></bean>
</beans>
BeanPostProcessor实现类:
package com.wxw.processor.initialize;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class WxwBeanPostProcessor implements BeanPostProcessor {
public WxwBeanPostProcessor(){
System.out.println("调用【BeanPostProcessor】构造方法!!!");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用【BeanPostProcessor】的【Before】方法!!!");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("调用【BeanPostProcessor】的【After】方法!!!");
return bean;
}
}
测试类:
package com.wxw.test;
import com.wxw.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestClass {
@Test
public void test1(){
System.out.println("=====================IoC容器初始化begin=========================");
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
System.out.println("=====================IoC容器初始化end=========================");
UserBean userBean = (UserBean) applicationContext.getBean("userBean");
System.out.println(userBean);
}
}
运行结果:
=====================IoC容器初始化begin=========================
调用【BeanFactoryPostProcessor】构造方法!!!
调用【BeanFactoryPostProcessor】类的postProcessBeanFactory方法!!!
调用【InstantiationAwareBeanPostProcessor】构造方法!!!
调用【BeanPostProcessor】构造方法!!!
=====================IoC容器初始化end=========================
调用【InstantiationAwareBeanPostProcessor】的Before方法!!!
调用【UserBean】的构造方法!!!
调用【InstantiationAwareBeanPostProcessor】的After方法!!!
调用【InstantiationAwareBeanPostProcessor】的postProcessProperties方法!!!
调用【UserBean】的【setName】方法!!!
调用【UserBean】的【setAge】方法!!!
调用【BeanFactoryAware】的【setBeanFactory】方法!!!
调用【BeanPostProcessor】的【Before】方法!!!
【InitializingBean】的【init】方法执行!!!
【init-method】配置的【init】方法执行!!!
调用【BeanPostProcessor】的【After】方法!!!
UserBean{name='Wxw', age=28}
4.2 时序图
5. Bean销毁阶段
在Bean销毁时,会执行DisposableBean接口destroy方法、xml中配置的destroy-method方法。
5.1 代码演示
UserBean类:
package com.wxw.pojo;
import lombok.Data;
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.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@Data
public class UserBean implements InitializingBean, BeanFactoryAware, ApplicationContextAware, DisposableBean {
private String name;
private Integer age;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("调用【ApplicationContextAware】的【setApplicationContext】方法!!!");
this.applicationContext = applicationContext;
}
public UserBean() {
System.out.println("调用【UserBean】的构造方法!!!");
}
public UserBean(String name, Integer age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
System.out.println("调用【UserBean】的【setName】方法!!!");
this.name = name;
}
public void setAge(Integer age) {
System.out.println("调用【UserBean】的【setAge】方法!!!");
this.age = age;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("调用【BeanFactoryAware】的【setBeanFactory】方法!!!");
this.beanFactory = beanFactory;
}
@Override
public String toString() {
return "UserBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("【InitializingBean】的【init】方法执行!!!");
}
public void init(){
System.out.println("【init-method】配置的【init】方法执行!!!");
}
@Override
public void destroy() throws Exception {
System.out.println("【DisposableBean】的【destroy】方法执行");
}
public void beanDestroy(){
System.out.println("【destroy-method】配置的【beanDestroy】方法执行!!!");
}
}
spring-config.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userBean" class="com.wxw.pojo.UserBean"
lazy-init="true"
init-method="init"
destroy-method="beanDestroy"
scope="singleton">
<property name="name" value="Wxw"/>
<property name="age" value="18"/>
</bean>
<bean id="wxwBeanFactoryPostProcessor" class="com.wxw.processor.ioc.WxwBeanFactoryPostProcessor"></bean>
<bean id="wxwInstantiationAwareBeanPostProcessor" class="com.wxw.processor.instantiation.WxwInstantiationAwareBeanPostProcessor"></bean>
<bean id="wxwBeanPostProcessor" class="com.wxw.processor.initialize.WxwBeanPostProcessor"></bean>
</beans>
测试类:
package com.wxw.test;
import com.wxw.pojo.UserBean;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestClass {
@Test
public void test1(){
System.out.println("=====================IoC容器初始化begin=========================");
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-config.xml");
System.out.println("=====================IoC容器初始化end=========================");
UserBean userBean = (UserBean) applicationContext.getBean("userBean");
System.out.println(userBean);
System.out.println("=====================IoC容器销毁begin=========================");
applicationContext.close();
System.out.println("=====================IoC容器销毁end=========================");
}
}
执行结果:
=====================IoC容器初始化begin=========================
调用【BeanFactoryPostProcessor】构造方法!!!
调用【BeanFactoryPostProcessor】类的postProcessBeanFactory方法!!!
调用【InstantiationAwareBeanPostProcessor】构造方法!!!
调用【BeanPostProcessor】构造方法!!!
=====================IoC容器初始化end=========================
调用【InstantiationAwareBeanPostProcessor】的Before方法!!!
调用【UserBean】的构造方法!!!
调用【InstantiationAwareBeanPostProcessor】的After方法!!!
调用【InstantiationAwareBeanPostProcessor】的postProcessProperties方法!!!
调用【UserBean】的【setName】方法!!!
调用【UserBean】的【setAge】方法!!!
调用【BeanFactoryAware】的【setBeanFactory】方法!!!
调用【ApplicationContextAware】的【setApplicationContext】方法!!!
调用【BeanPostProcessor】的【Before】方法!!!
【InitializingBean】的【init】方法执行!!!
【init-method】配置的【init】方法执行!!!
调用【BeanPostProcessor】的【After】方法!!!
UserBean{name='Wxw', age=28}
=====================IoC容器销毁begin=========================
【DisposableBean】的【destroy】方法执行
【destroy-method】配置的【beanDestroy】方法执行!!!
=====================IoC容器销毁end=========================
进程已结束,退出代码为 0