拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。 网站地图
IMG-LOGO
主页 文章列表 参与Bean的生命周期

参与Bean的生命周期

by 白鹭 - 2022-01-25 1914 0 0

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框架产生耦合,

回传目录    下载代码

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *