前言
本篇文章主要是要介紹如何在Spring IoC 容器中 如何管理Spring Bean生命周期型檀。
在應(yīng)用開(kāi)發(fā)中冗尤,常常需要執(zhí)行一些特定的初始化工作,這些工作都是相對(duì)比較固定的胀溺,比如建立數(shù)據(jù)庫(kù)連接裂七,打開(kāi)網(wǎng)絡(luò)連接等,同時(shí)仓坞,在結(jié)束服務(wù)時(shí)背零,也有一些相對(duì)固定的銷(xiāo)毀工作需要執(zhí)行。為了便于這些工作的設(shè)計(jì)无埃,Spring IoC容器提供了相關(guān)的功能徙瓶,可以讓?xiě)?yīng)用定制Bean的初始化和銷(xiāo)毀過(guò)程。
Spring Bean 生命周期
圖片描述
先來(lái)看看 Spring Bean 的生命周期流程圖嫉称。結(jié)合圖看后面的描述會(huì)更輕松一點(diǎn)哦侦镇。
文字描述
- Bean容器在配置文件中找到Spring Bean的定義。
- Bean容器使用Java Reflection API創(chuàng)建Bean的實(shí)例织阅。
- 如果聲明了任何屬性壳繁,聲明的屬性會(huì)被設(shè)置。如果屬性本身是Bean蒲稳,則將對(duì)其進(jìn)行解析和設(shè)置氮趋。
- 如果Bean類(lèi)實(shí)現(xiàn)
BeanNameAware
接口,則將通過(guò)傳遞Bean的名稱來(lái)調(diào)用setBeanName()
方法江耀。 - 如果Bean類(lèi)實(shí)現(xiàn)
BeanClassLoaderAware
接口剩胁,則將通過(guò)傳遞加載此Bean的ClassLoader對(duì)象的實(shí)例來(lái)調(diào)用setBeanClassLoader()
方法。 - 如果Bean類(lèi)實(shí)現(xiàn)
BeanFactoryAware
接口祥国,則將通過(guò)傳遞BeanFactory對(duì)象的實(shí)例來(lái)調(diào)用setBeanFactory()
方法昵观。 - 如果有任何與BeanFactory關(guān)聯(lián)的BeanPostProcessors對(duì)象已加載Bean,則將在設(shè)置Bean屬性之前調(diào)用
postProcessBeforeInitialization()
方法舌稀。 - 如果Bean類(lèi)實(shí)現(xiàn)了
InitializingBean
接口啊犬,則在設(shè)置了配置文件中定義的所有Bean屬性后,將調(diào)用afterPropertiesSet()
方法壁查。 - 如果配置文件中的Bean定義包含
init-method
屬性觉至,則該屬性的值將解析為Bean類(lèi)中的方法名稱,并將調(diào)用該方法睡腿。 - 如果為Bean Factory對(duì)象附加了任何Bean 后置處理器语御,則將調(diào)用
postProcessAfterInitialization()
方法峻贮。 - 如果Bean類(lèi)實(shí)現(xiàn)
DisposableBean
接口,則當(dāng)Application不再需要Bean引用時(shí)应闯,將調(diào)用destroy()
方法纤控。 - 如果配置文件中的Bean定義包含
destroy-method
屬性,那么將調(diào)用Bean類(lèi)中的相應(yīng)方法定義碉纺。
實(shí)例演示
接下來(lái)船万,我們用一個(gè)簡(jiǎn)單的DEMO來(lái)演示一下,整個(gè)生命周期的流轉(zhuǎn)過(guò)程骨田,加深你的印象耿导。
- 定義一個(gè)
Person
類(lèi),實(shí)現(xiàn)了DisposableBean, InitializingBean, BeanFactoryAware, BeanNameAware
這4個(gè)接口盛撑,同時(shí)還有自定義的init-method
和destroy-method
碎节。這里捧搞,如果不了解這幾個(gè)接口的讀者抵卫,可以先去看看這幾個(gè)接口的定義。
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!");
}
}
- 定義一個(gè)
MyBeanPostProcessor
實(shí)現(xiàn)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"?>
<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 name="myBeanPostProcessor" class="ric.study.demo.ioc.life_cycle_demo_set.MyBeanPostProcessor" />
<bean name="personBean" class="ric.study.demo.ioc.life_cycle_demo_set.Person"
init-method="init" destroy-method="destroyMethod">
<property name="name" value="Richard Yi" />
</bean>
</beans>
- 啟動(dòng)容器、銷(xiāo)毀容器
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 invoked
setBeanFactory method of person is invoked
post Process Before Initialization is invoked
afterPropertiesSet method of person bean is invoked!
custom init method of person bean is invoked!
post Process after Initialization is invoked
DisposableBean Destroy method of person bean is invoked!
custom Destroy method of person bean is invoked!
可以看到這個(gè)結(jié)果和我們上面描述的一樣晚树。
源碼解析
下面我們從源碼角度來(lái)看看姻采,上述描述的調(diào)用是如何實(shí)現(xiàn)的。
實(shí)際上如果你看過(guò)我之前的文章 Spring IoC 依賴注入 源碼解析的話爵憎,應(yīng)該知道上述調(diào)用的具體實(shí)現(xiàn)慨亲。
這里相當(dāng)于把相關(guān)部分再拎出來(lái)講一遍。
容器初始化
Spring IoC 依賴注入的階段宝鼓,創(chuàng)建Bean有三個(gè)關(guān)鍵步驟
- createBeanInstance() 實(shí)例化
- populateBean(); 屬性裝配
- initializeBean() 處理Bean初始化之后的各種回調(diào)事件
其中刑棵,initializeBean()
負(fù)責(zé)處理Bean初始化后的各種回調(diào)事件。
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
// 涉及到的回調(diào)接口點(diǎn)進(jìn)去一目了然愚铡,代碼都是自解釋的
// BeanNameAware蛉签、BeanClassLoaderAware或BeanFactoryAware
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessBeforeInitialization 回調(diào)
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// init-methods
// 或者是實(shí)現(xiàn)了InitializingBean接口,會(huì)調(diào)用afterPropertiesSet() 方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回調(diào)
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
其中invokeAwareMethods
會(huì)先調(diào)用一系列的***Aware
接口實(shí)現(xiàn)
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
然后再執(zhí)行 BeanPostProcessor
的 postProcessBeforeInitialization
回調(diào)
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
然后再調(diào)用 初始化方法沥寥,其中包括 InitializingBean
的afterPropertiesSet
方法和指定的init-method
方法碍舍,
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((InitializingBean) bean).afterPropertiesSet();
return null;
}
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null) {
String initMethodName = mbd.getInitMethodName();
if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
最后再執(zhí)行 BeanPostProcessor
的 postProcessAfterInitialization
回調(diào)
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessAfterInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
好的,到這里我們介紹了Spring 容器初始化過(guò)程Bean加載過(guò)程當(dāng)中的各種回調(diào)實(shí)現(xiàn)邑雅,下面介紹Spring 容器銷(xiāo)毀階段片橡。
容器關(guān)閉
與Bean初始化類(lèi)似,當(dāng)容器關(guān)閉時(shí)淮野,可以看到對(duì)Bean銷(xiāo)毀方法的調(diào)用捧书。銷(xiāo)毀過(guò)程是這樣的狂塘。順著close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> bean.destroy()
,會(huì)看到最終調(diào)用Bean的銷(xiāo)毀方法鳄厌。
protected void destroyBean(String beanName, DisposableBean bean) {
// 忽略
// Actually destroy the bean now...
if (bean != null) {
try {
bean.destroy();
}
catch (Throwable ex) {
logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
}
}
// 忽略
}
這里注意哦荞胡,這個(gè)Bean的類(lèi)型實(shí)際上是DisposableBeanAdapter
,DisposableBeanAdapter
是管理Spring Bean的銷(xiāo)毀的,實(shí)際上這里運(yùn)用了適配器模式了嚎。再來(lái)看看destroy()
的具體方法泪漂。
@Override
public void destroy() {
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
}
try {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
@Override
public Object run() throws Exception {
((DisposableBean) bean).destroy();
return null;
}
}, acc);
}
else {
// 調(diào)用 DisposableBean 的 destroy()方法
((DisposableBean) bean).destroy();
}
}
catch (Throwable ex) {
String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
if (logger.isDebugEnabled()) {
logger.warn(msg, ex);
}
else {
logger.warn(msg + ": " + ex);
}
}
}
if (this.destroyMethod != null) {
// 調(diào)用 設(shè)置的destroyMethod
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod();
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
BeanPostProcessor 是什么時(shí)候注冊(cè)到容器的?
前面只介紹了BeanPostProcessor類(lèi)在 Spring Bean 生命周期中的回調(diào)實(shí)現(xiàn)歪泳,卻沒(méi)有說(shuō)明 BeanPostProcessor 是什么時(shí)候注冊(cè)到容器的萝勤。下面我們來(lái)介紹下。
在Spring IoC 容器初始化的時(shí)候呐伞,容器會(huì)做一些初始化操作敌卓,其中就包括了BeanPostProcessor的register過(guò)程。詳細(xì)的過(guò)程可以看我這篇IoC 容器初始化伶氢。
這里直接放源碼吧趟径。
源碼位置AbstractApplicationContext#refresh()
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
// 在這里
registerBeanPostProcessors(beanFactory);
// ....忽略
}
}
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
源碼位置PostProcessorRegistrationDelegate#registerBeanPostProcessors()
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// step1
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// step2
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
List<String> orderedPostProcessorNames = new ArrayList<String>();
List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// step3
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
上述過(guò)程可以分成四步:
- 通過(guò)
beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
方法獲取beanFactory里繼承了BeanPostProcessor接口的name的集合; - 把后置器beans分為
PriorityOrdered癣防、Ordered蜗巧、nonOrdered
三大類(lèi),前兩類(lèi)是增加了排序條件的后置器蕾盯;(Spring可以通過(guò)PriorityOrdered
和Ordered
接口控制處理器的優(yōu)先級(jí))幕屹,這里實(shí)際上還有一類(lèi)是MergedBeanDefinitionPostProcessor
,不是核心點(diǎn)级遭,不展開(kāi)講望拖。 - 第三步可以分為以下小步
-
priorityOrderedPostProcessors
,先排序后注冊(cè) -
orderedPostProcessors
挫鸽,先排序后注冊(cè) - 注冊(cè)
nonOrderedPostProcessors
说敏,就是一般的處理器 -
internalPostProcessors
,先排序后注冊(cè) - 注冊(cè)一個(gè)
ApplicationListenerDetector
的 processor
-
DisposableBeanAdapter 什么時(shí)候注冊(cè)到容器的掠兄?
DisposableBeanAdapter
和上文的BeanPostProcessor
的抽象層級(jí)不同像云,這個(gè)是和Bean綁定的,所以它的注冊(cè)時(shí)機(jī)是在Spring Bean的依賴注入階段蚂夕,詳細(xì)源碼可以看我的這篇文章Spring IoC 依賴注入 源碼解析迅诬。
源碼位置:AbstractAutowireCapableBeanFactory#doCreateBean()
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// 省略前面的超多步驟,想了解的可以去看源碼或者我的那篇文章
// Register bean as disposable.
// 這里就是DisposableBeanAdapter的注冊(cè)步驟了
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
源碼位置:AbstractBeanFactory#registerDisposableBeanIfNecessary()
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
// 注冊(cè)一個(gè)DisposableBean實(shí)現(xiàn)婿牍,該實(shí)現(xiàn)將執(zhí)行給定bean的所有銷(xiāo)毀工作侈贷。
// 包括:DestructionAwareBeanPostProcessors,DisposableBean接口,自定義destroy方法俏蛮。
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
結(jié)語(yǔ)
至此撑蚌,Spring Bean的整個(gè)生命周期算是講解完了,從容器初始化到容器銷(xiāo)毀搏屑,以及回調(diào)事件的注冊(cè)時(shí)機(jī)等方面都說(shuō)明了一下争涌,希望能對(duì)你有所幫助。
本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布辣恋!