参与Bean的生命周期

Spring容器是个神奇的魔法师。瞧!我们把写好的类和配置文件放进Spring容器里,Spring容器就能变出各种各样的Bean。之后,各种各样的Bean存在Spring容器里,相互依赖,彼此合作,又构成一个繁忙的应用程序,处理着来自远方的各种请求;直到应用程序退出,Spring容器关闭,Bean才消失在历史的长河中。由此可见,存在Spring容器里的Bean有个从诞生到消亡的过程,这个过程俗称Bean的生命周期,具体如下:
01.运行Web应用程序
02.创建Spring容器
03.加载配置文件生成Bean的定义
04.创建实现了BeanFactoryPostProcessor接口的Bean,调用postProcessBeanFactory方法
05.创建实现了BeanPostProcessor接口的Bean
06.创建其它类型的Bean
07.通过属性注入依赖
08.调用Aware接口的方法
09.调用postProcessBeforeInitialization方法
10.调用afterPropertiesSet方法初始化Bean
11.调用postProcessAfterInitialization方法
12.存在Spring容器里的Bean开始支持整个应用程序的运行
13.退出Web应用程序
14.关闭Spring容器
15.调用destroy方法销毁Bean

可以看到Bean的生命周期从开始到结束总共经历十五个阶段,每个阶段都有每个阶段该做的事。现在,让我们以庖丁解牛的手法剖开各个阶段,瞧瞧里头具体是怎样的,以及怎样写些代码参与进去,做些我们想做的事。

阶段一:运行Web应用程序

这是事情的开端。在此阶段,Web容器将会加载和初始化Web应用程序,使之运行起来。

阶段二:创建Spring容器

Web容器初始化Web应用程序的时候,Web应用程序将会根据部署描述文件提供的信息创建两个Spring容器:一个是根应用上下文;一个是Servlet应用上下文。每个容器都有自己创建和管理着的Bean。Bean的生命周期是与Bean所在的容器关联的。

阶段三:加载配置文件生成Bean的定义

Web应用程序创建Spring容器的时候,Spring容器将会加载配置文件,解析配置文件,根据配置文件提供的信息生成BeanDefinition对象。BeanDefinition对象俗称Bean的定义,保存着关于如何创建Bean的信息。

阶段四:创建实现了BeanFactoryPostProcessor接口的Bean,调用postProcessBeanFactory方法

BeanFactoryPostProcessor是Spring提供的一个接口,具体如下:

1 public interface BeanFactoryPostProcessor {
2     void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
3             throws BeansException;
4 }

Spring容器加载配置文件生成Bean的定义之后,开始根据Bean的定义提供的信息创建各种Bean。创建各种Bean之前,Spring容器会先看看哪些Bean实现了BeanFactoryPostProcessor接口,并在找到之后首先创建这种类型的Bean,直到创建完毕才会接着创建其它类型的Bean

Spring容器创建完成所有实现了BeanFactoryPostProcessor接口的Bean之后,在开始创建其它类型的Bean之前,会先调用那些实现了BeanFactoryPostProcessor接口的Bean的postProcessBeanFactory方法。我们可在BeanFactoryPostProcessor接口的实现里修改Bean的定义,改变Spring容器即将创建的Bean的样子。

比如,Spring提供的PropertySourcesPlaceholderConfigurer类就实现了BeanFactoryPostProcessor接口,具有读取属性文件,使用属性文件的值替换Bean的定义里保存着的属性占位符,从而把属性文件的值作为字面量值注入Bean里的功能。我们将在介绍属性占位符的时候详细介绍这些内容,这里暂不详述。

阶段五:创建实现了BeanPostProcessor接口的Bean

BeanPostProcessor是Spring提供的一个接口,具体如下:

 1 public interface BeanPostProcessor {
 2     @Nullable
 3     default Object postProcessBeforeInitialization(Object bean, String beanName) 
 4             throws BeansException {
 5         return bean;
 6     }
 7 
 8     @Nullable
 9     default Object postProcessAfterInitialization(Object bean, String beanName) 
10             throws BeansException {
11         return bean;
12     }
13 }

Spring容器完成所有实现了BeanFactoryPostProcessor接口的Bean的postProcessBeanFactory方法的调用之后,开始检查Bean的定义,看看哪些Bean实现了BeanPostProcessor接口,并在找到之后开始创建这些Bean,直到创建完毕才会接着创建其它类型的Bean。BeanPostProcessor接口是为了参与Bean的初始化准备的。至于怎样参与,请往下继续阅读。

阶段六:创建其它类型的Bean

Spring容器创建完成所有实现了BeanPostProcessor接口的Bean之后,开始通过反射技术调用构造函数,创建既没实现BeanFactoryPostProcessor接口,也没实现BeanPostProcessor接口的其它类型的Bean

阶段七:通过属性注入依赖

Spring容器调用Bean的构造函数完成Bean的创建之后,开始通过属性注入依赖,完成Bean的装配。

阶段八:调用Aware接口的方法

Spring提供了很多继承了Aware接口的接口。如果我们的Bean实现了这些接口,Spring容器就能通过回调的方式把那些框架相关的Bean传给我们的Bean,使我们的Bean能够使用框架相关的Bean做些事情。常见的框架相关的Bean有BeanFactory,ApplicationContext,等等。

针对BeanFactory对象,Spring提供了BeanFactoryAware接口,具体如下:

1 public interface BeanFactoryAware extends Aware {
2     void setBeanFactory(BeanFactory beanFactory) throws BeansException;
3 }

可以看到BeanFactoryAware继承了Aware接口,定义了 void setBeanFactory(BeanFactory beanFactory) 这样一个接受BeanFactory类型的参数的方法。如果我们的Bean实现了BeanFactoryAware接口,Spring容器完成Bean的属性的注入之后,就会以Spring容器里存在着的BeanFactory对象作为参数调用setBeanFactory方法,把BeanFactory对象交给我们的Bean,使我们的Bean能用BeanFactory对象做些事情。

针对ApplicationContext对象,Spring提供了ApplicationContextAware接口,具体如下:

1 public interface ApplicationContextAware extends Aware {
2     void setApplicationContext(ApplicationContext applicationContext) 
3             throws BeansException;
4 }

可以看到ApplicationContextAware继承了Aware接口,定义了 void setApplicationContext( ApplicationContext applicationContext) 这样一个接受ApplicationContext类型的参数的方法。如果我们的Bean实现了ApplicationContextAware接口,Spring容器完成Bean的属性的注入之后,就会以Spring容器里存在着的ApplicationContext对象作为参数调用setApplicationContext方法,把ApplicationContext对象交给我们的Bean,使我们的Bean能用ApplicationContext对象做些事情。

值得注意的是,BeanFactoryAware和ApplicationContextAware都继承了Aware接口。Aware接口具体如下:

1 public interface Aware {
2 }

里面空落落的,一个成员也没有。因为Aware接口主要作为父接口用于派生各种各样的Aware接口,使我们的Bean实现这些Aware接口之后,Spring容器可把Spring框架相关的对象作为参数调用这些接口定义的方法,让我们的Bean能用Spring框架相关的对象做些事情。

阶段九:调用postProcessBeforeInitialization方法

完成所有Aware接口的方法的调用之后,Spring容器开始进行Bean的初始化。开始初始化Bean之前,Spring容器会先查看一下Spring容器里存不存在实现了BeanPostProcessor接口的Bean。注意,实现了BeanPostProcessor接口的Bean是在阶段五的时候创建的。如果存在,则会调用所有实现了BeanPostProcessor接口的Bean的postProcessBeforeInitialization方法,在Bean的初始化之前做些事情。

因此,如果我们想在Bean的初始化开始之前做些事情,可以定义一些实现了BeanPostProcessor接口的类。

阶段十:调用afterPropertiesSet方法初始化Bean

afterPropertiesSet方法是InitializingBean接口定义的一个方法,具体如下:

1 public interface InitializingBean {
2     void afterPropertiesSet() throws Exception;
3 }

Spring容器完成所有实现了BeanPostProcessor接口的Bean的postProcessBeforeInitialization方法的调用之后,就会开始检查我们的Bean需不需要进行初始化。如果需要,则开始进行初始化。初始化过程从先到后是这样的:
1.检查Bean是否定义了带有@PostConstruct注解的初始化方法。如果定义了,则调用带有@PostConstruct注解的方法进行初始化。
2.检查Bean是否实现了InitializingBean接口。如果实现了,则调用afterPropertiesSet方法进行初始化。
3.检查XML配置文件的<bean>元素是否通过init-method属性指定了初始化方法。如果指定了,则调用初始化方法进行初始化。

还有,除了可以通过<bean>元素的init-method属性指定初始化方法之外,也可通过根元素<beans>的default-init-method属性为所有的Bean指定一个默认的初始化方法。如果同时指定了<bean>元素的init-method属性和根元素<beans>的default-init-method属性,则<bean>元素的init-method属性将会覆盖根元素<beans>的default-init-method属性指定的初始化方法。

另外,如果采用配置类进行配置的话,则可通过@Bean注解的initMethod属性指定初始化方法。

阶段十一:调用postProcessAfterInitialization方法

Spring容器完成Bean的初始化之后,开始检查Spring容器里存不存在实现了BeanPostProcessor接口的Bean。注意,实现了BeanPostProcessor接口的Bean是在阶段五的时候创建的。如果存在,则会调用所有实现了BeanPostProcessor接口的Bean的postProcessAfterInitialization方法,在完成Bean的初始化之后做些事情。

因此,如果我们想在Bean的初始化完成之后做些事情,可以定义一些实现了BeanPostProcessor接口的类。

阶段十二:存在Spring容器里的Bean开始支持整个应用程序的运行

Spring容器完成所有Bean的创建和初始化之后,开始支持整个应用程序的运行,处理着来自远方的各种请求。

阶段十三:退出Web应用程序

Web应用程序退出运行。

阶段十四:关闭Spring容器

Web应用程序退出的时候,Spring容器将被关闭。

阶段十五:调用destroy方法销毁Bean

destroy方法是DisposableBean接口定义的一个方法,具体如下:

1 public interface DisposableBean {
2     void destroy() throws Exception;
3 }

Spring容器关闭的时候,将会检查我们的Bean需不需要做些销毁工作。如果需要,则开始进行销毁。销毁过程从先到后是这样的:
1.检查Bean是否定义了带有@PreDestroy注解的销毁方法。如果定义了,则调用带有@PreDestroy注解的方法进行销毁。
2.检查Bean是否实现了DisposableBean接口。如果实现了,则调用destroy方法进行销毁。
3.检查XML配置文件的<bean>元素是否通过destroy-method属性指定了销毁方法。如果指定了,则调用销毁方法进行销毁。

还有,除了可以通过<bean>元素的destroy-method属性指定销毁方法之外,也可通过根元素<beans>的default-destroy-method属性为所有的Bean指定一个默认的销毁方法。如果同时指定了<bean>元素的destroy-method属性和根元素<beans>的default-destroy-method属性,则<bean>元素的destroy-method属性将会覆盖根元素<beans>的default-destroy-method属性指定的销毁方法。

另外,如果采用配置类进行配置的话,则可通过@Bean注解的destroyMethod属性指定销毁方法。

于是,Bean的整个生命周期我们已经理清楚了,也知道如何写些代码参与进去。需要特别提醒的是,虽然我们可以通过实现诸如BeanFactoryPostProcessor,BeanPostProcessor这样的接口达到参与Bean的生命周期的目的;可是,这样却会导致我们的Bean与Spring框架产生耦合。

返回目录    下载代码

posted @ 2022-01-02 00:59  林雪波  阅读(170)  评论(0编辑  收藏  举报