Spring之bean的生命周期
在传统的Java应用中,bean的生命周期很简单,使用Java关键字 new 进行Bean 的实例化,然后该Bean 就能够使用了。一旦bean不再被使用,则由Java自动进行垃圾回收。
相比之下,Spring管理Bean的生命周期就复杂多了,正确理解Bean 的生命周期非常重要,因为Spring对Bean的管理可扩展性非常强,下面展示了一个Bean的构造过程
- Bean 容器找到配置文件中 Spring Bean 的定义。
- Bean 容器利用 Java Reflection API 创建一个 Bean 的实例。
- 如果涉及到一些属性值 利用 set()方法设置一些属性值。
- 如果实现了其他 *.Aware接口,就调用相应的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessBeforeInitialization() 方法
- 如果 Bean 实现了InitializingBean接口,执行afterPropertiesSet()方法。
- 如果 Bean 在配置文件中的定义包含 init-method 属性,执行指定的方法。
- 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执行postProcessAfterInitialization() 方法
- 当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接口,执行 destroy() 方法。
- 当要销毁 Bean 的时候,如果 Bean 在配置文件中的定义包含 destroy-method 属性,执行指定的方法。
在 BeanFactory
的注释里,有这么一段话,如下图所示:
代码演示
- 新建一个
User
类,让其实现接口BeanNameAware
、BeanFactoryAware
、InitializingBean
和DiposableBean
这4个接口,以及编写userInit()
和userDestroy()
两个方法,对应配置文件中<bean>
的init-method
和destroy-method
。
package com.wqing.domain; import org.springframework.beans.BeansException; import org.springframework.beans.factory.*; /** * @Description 用于演示 Bean 的生命周期 * @Author wqing * @Date 2022/8/11 15:37 */ public class User implements BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean { private String name; private Integer age; private BeanFactory beanFactory; private String beanName; public User() { System.out.println("[构造器]--调用Person的构造函数进行实例化"); } public String getName() { return name; } public void setName(String name) { System.out.println("[属性填充]--注入属性name"); this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { System.out.println("[属性填充]--注入属性age"); this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '/'' + ", age=" + age + '}'; } //这是 BeanFactoryAware 接口的方法 @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("[BeanFactoryAware]--执行BeanFactoryAware.setBeanFactory(),beanFactory为:" + beanFactory); this.beanFactory = beanFactory; } //这是 BeanNameAware 接口的方法 @Override public void setBeanName(String name) { System.out.println("[BeanNameAware]--执行BeanNameAware.setBeanName(),beanName为: " + name); this.beanName = name; } //这是 DisposableBean 接口的方法 @Override public void destroy() throws Exception { System.out.println("[DisposableBean]--执行DisposableBean.destroy()"); } //这是 InitializingBean 接口的方法 @Override public void afterPropertiesSet() throws Exception { System.out.println("[InitializingBean]--执行InitializingBean.afterPropertiesSet()"); } // 通过<bean>的init-method属性指定的初始化方法 public void userInit() { System.out.println("[init-method]--执行<bean>的init-method属性指定的初始化方法"); } // 通过<bean>的destroy-method属性指定的初始化方法 public void userDestroy() { System.out.println("[destroy-method]--执行<bean>的destroy-method属性指定的销毁方法"); } }
- 自定义
MyBeanPostProcessor
实现BeanPostProcessor
package com.wqing.domain; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** * @Description * @Author 王清 * @Date 2022/8/11 16:06 */ public class MyBeanPostProcessor implements BeanPostProcessor { /** * 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务 */ @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("[BeanPostProcessor]--执行BeanPostProcessor.postProcessBeforeInitialization()"); return bean; } /** * 实例化、依赖注入、初始化完毕时执行 */ @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("[BeanPostProcessor]--执行BeanPostProcessor.postProcessAfterInitialization()"); return bean; } }
BeanPostProcessor
接口包括2个方法postProcessAfterInitialization
和postProcessBeforeInitialization
,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。
- 编写
application.xml
,将User
和MyBeanPostProcessor
注册进容器
<?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="user" class="com.wqing.domain.User" init-method="userInit" destroy-method="userDestroy"> <property name="name" value="张三"/> <property name="age" value="20"/> </bean> <bean id="myBeanPostProcessor" class="com.wqing.domain.MyBeanPostProcessor"/> </beans>
- 编写测试类
package com.wqing; import com.wqing.domain.User; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * @Description * @Author wqing * @Date 2022/8/5 14:38 */ public class Test { public static void main(String[] args) { System.out.println("容器开始创建"); ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml"); User bean = context.getBean(User.class); System.out.println("使用 bean"); System.out.println(bean); System.out.println("容器开始销毁"); context.close(); } }
执行结果
容器开始创建 [构造器]--调用Person的构造函数进行实例化 [属性填充]--注入属性name [属性填充]--注入属性age [BeanNameAware]--执行BeanNameAware.setBeanName(),beanName为: user [BeanFactoryAware]--执行BeanFactoryAware.setBeanFactory(),beanFactory为:org.springframework.beans.factory.support.DefaultListableBeanFactory@38082d64: defining beans [user,myBeanPostProcessor]; root of factory hierarchy [BeanPostProcessor]--执行BeanPostProcessor.postProcessBeforeInitialization() [InitializingBean]--执行InitializingBean.afterPropertiesSet() [init-method]--执行<bean>的init-method属性指定的初始化方法 [BeanPostProcessor]--执行BeanPostProcessor.postProcessAfterInitialization() 使用 bean User{name='张三', age=20} 容器开始销毁 [DisposableBean]--执行DisposableBean.destroy() [destroy-method]--执行<bean>的destroy-method属性指定的销毁方法