前言
本篇文章主要是要介绍如何在Spring IoC 容器中 如何管理Spring Bean生命周期。
在应用开发中,常常需要执行一些特定的初始化工作,这些工作都是相对比较固定的,比如建立数据库连接,打开网络连接等,同时,在结束服务时,也有一些相对固定的销毁工作需要执行。为了便于这些工作的设计,Spring IoC容器提供了相关的功能,可以让应用定制Bean的初始化和销毁过程。
Spring Bean 生命周期
图片描述
先来看看 Spring Bean 的生命周期流程图。结合图看后面的描述会更轻松一点哦。
![cb3a70451f6ded4b9ad4313135d6f553.png](https://i-blog.csdnimg.cn/blog_migrate/e2836a45c59e499dfedead74ebfb554d.jpeg)
文字描述
- Bean容器在配置文件中找到Spring Bean的定义。
- Bean容器使用Java Reflection API创建Bean的实例。
- 如果声明了任何属性,声明的属性会被设置。如果属性本身是Bean,则将对其进行解析和设置。
- 如果Bean类实现 BeanNameAware 接口,则将通过传递Bean的名称来调用 setBeanName() 方法。
- 如果Bean类实现 BeanClassLoaderAware 接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用 setBeanClassLoader() 方法。
- 如果Bean类实现 BeanFactoryAware 接口,则将通过传递BeanFactory对象的实例来调用 setBeanFactory() 方法。
- 如果有任何与BeanFactory关联的BeanPostProcessors对象已加载Bean,则将在设置Bean属性之前调用 postProcessBeforeInitialization() 方法。
- 如果Bean类实现了 InitializingBean 接口,则在设置了配置文件中定义的所有Bean属性后,将调用 afterPropertiesSet() 方法。
- 如果配置文件中的Bean定义包含 init-method 属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法。
- 如果为Bean Factory对象附加了任何Bean 后置处理器,则将调用 postProcessAfterInitialization() 方法。
- 如果Bean类实现 DisposableBean 接口,则当Application不再需要Bean引用时,将调用 destroy() 方法。
- 如果配置文件中的Bean定义包含 destroy-method 属性,那么将调用Bean类中的相应方法定义。
实例演示
接下来,我们用一个简单的DEMO来演示一下,整个声明周期的流转过程,加深你的印象。
- 定义一个 Person 类,实现了 DisposableBean, InitializingBean, BeanFactoryAware, BeanNameAware 这4个接口,同时还有自定义的 init-method 和 destroy-method 。这里,如果不了解这几个接口的读者,可以先去看看这几个接口的定义。
public class Person implements DisposableBean, InitializingBean, BeanFactoryAware, BeanNameAware { private String name; Person() { System.out.println("Constructor of person bean is invoked!"); } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("setBeanFactory method of person is invoked"); } @Override public void setBeanName(String name) { System.out.println("setBeanName method of person is invoked"); } public void init() { System.out.println("custom init method of person bean is invoked!"); } //Bean initialization code equals to @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet method of person bean is invoked!"); } //Bean destruction code @Override public void destroy() throws Exception { System.out.println("DisposableBean Destroy method of person bean is invoked!"); } public void destroyMethod() { System.out.println("custom Destroy method of person bean is invoked!"); }}
- 定义一个 MyBeanPostProcessor 实现 BeanPostProcessor 接口。
public class MyBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("post Process Before Initialization is invoked"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("post Process after Initialization is invoked"); return bean; }}
- 配置文件,指定 init-method 和 destroy-method 属性
<?xml version="1.0" encoding="UTF-8"?>
- 启动容器、销毁容器
public class Main { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring-config-1.xml"); ((ClassPathXmlApplicationContext) context).destroy(); }}
- 输出
Constructor of person bean is invoked!setBeanName method of person is invokedsetBeanFactory method of person is invokedpost Process Before Initialization is invokedafterPropertiesSet method of person bean is invoked!custom init method of person bean is invoked!post Process after Initialization is invokedDisposableBean Destroy method of person bean is invoked!custom Destroy method of person bean is invoked!
可以看到这个结果和我们上面描述的一样。
源码解析
下面我们从源码角度来看看,上述描述的调用是如何实现的。
实际上如果你看过我之前的文章 Spring IoC 依赖注入 源码解析 的话,应该知道上述调用的具体实现。
这里相当于把相关部分再拎出来讲一遍。
容器初始化
Spring IoC 依赖注入的阶段,创建Bean有三个关键步骤
- createBeanInstance() 实例化
- populateBean(); 属性装配
- initializeBean() 处理Bean初始化之后的各种回调事件
其中, initializeBean() 负责处理Bean初始化后的各种回调事件。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) { if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction() { @Override public Object run() { invokeAwareMethods(beanName, bean); return null; } }, getAccessControlContext()); } else { // 涉及到的回调接口点进去一目了然,代码都是自解释的 // BeanNameAware、BeanClassLoaderAware或BeanFactoryAware invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; if (mbd == null || !mbd.isSynthetic()) { // BeanPostProcessor 的 postProcessBeforeInitialization 回调 wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // init-methods // 或者是实现了InitializingBean接口,会调用afterPropertiesSet() 方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed