本篇文章主要是要介紹如何在Spring IoC 容器中 如何管理Spring Bean生命週期。php
在應用開發中,經常須要執行一些特定的初始化工做,這些工做都是相對比較固定的,好比創建數據庫鏈接,打開網絡鏈接等,同時,在結束服務時,也有一些相對固定的銷燬工做須要執行。爲了便於這些工做的設計,Spring IoC容器提供了相關的功能,可讓應用定製Bean的初始化和銷燬過程。java
先來看看 Spring Bean 的生命週期流程圖。結合圖看後面的描述會更輕鬆一點哦。spring
BeanNameAware
接口,則將經過傳遞Bean的名稱來調用setBeanName()
方法。BeanClassLoaderAware
接口,則將經過傳遞加載此Bean的ClassLoader對象的實例來調用setBeanClassLoader()
方法。BeanFactoryAware
接口,則將經過傳遞BeanFactory對象的實例來調用setBeanFactory()
方法。postProcessBeforeInitialization()
方法。InitializingBean
接口,則在設置了配置文件中定義的全部Bean屬性後,將調用afterPropertiesSet()
方法。init-method
屬性,則該屬性的值將解析爲Bean類中的方法名稱,並將調用該方法。postProcessAfterInitialization()
方法。DisposableBean
接口,則當Application再也不須要Bean引用時,將調用destroy()
方法。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"?>
<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>
複製代碼
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!
複製代碼
能夠看到這個結果和咱們上面描述的同樣。bash
下面咱們從源碼角度來看看,上述描述的調用是如何實現的。網絡
實際上若是你看過我以前的文章 Spring IoC 依賴注入 源碼解析的話,應該知道上述調用的具體實現。app
這裏至關於把相關部分再拎出來說一遍。ide
Spring IoC 依賴注入的階段,建立Bean有三個關鍵步驟post
其中,initializeBean()
負責處理Bean初始化後的各類回調事件。ui
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 {
// 涉及到的回調接口點進去一目瞭然,代碼都是自解釋的
// 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", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
// BeanPostProcessor 的 postProcessAfterInitialization 回調
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
複製代碼
其中invokeAwareMethods
會先調用一系列的***Aware
接口實現
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);
}
}
}
複製代碼
而後再執行 BeanPostProcessor
的 postProcessBeforeInitialization
回調
@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;
}
複製代碼
而後再調用 初始化方法,其中包括 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);
}
}
}
複製代碼
最後再執行 BeanPostProcessor
的 postProcessAfterInitialization
回調
@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 容器初始化過程Bean加載過程中的各類回調實現,下面介紹Spring 容器銷燬階段。
與Bean初始化相似,當容器關閉時,能夠看到對Bean銷燬方法的調用。銷燬過程是這樣的。順着close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> bean.destroy()
,會看到最終調用Bean的銷燬方法。
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);
}
}
// 忽略
}
複製代碼
這裏注意哦,這個Bean的類型其實是DisposableBeanAdapter
,DisposableBeanAdapter
是管理Spring Bean的銷燬的,實際上這裏運用了適配器模式。再來看看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 {
// 調用 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) {
// 調用 設置的destroyMethod
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod();
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
複製代碼
前面只介紹了BeanPostProcessor類在 Spring Bean 生命週期中的回調實現,卻沒有說明 BeanPostProcessor 是何時註冊到容器的。下面咱們來介紹下。
在Spring IoC 容器初始化的時候,容器會作一些初始化操做,其中就包括了BeanPostProcessor的register過程。詳細的過程能夠看我這篇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));
}
複製代碼
上述過程能夠分紅四步:
beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
方法獲取beanFactory裏繼承了BeanPostProcessor接口的name的集合;PriorityOrdered、Ordered、nonOrdered
三大類,前兩類是增長了排序條件的後置器;(Spring能夠經過PriorityOrdered
和Ordered
接口控制處理器的優先級),這裏實際上還有一類是MergedBeanDefinitionPostProcessor
,不是核心點,不展開講。priorityOrderedPostProcessors
,先排序後註冊orderedPostProcessors
,先排序後註冊nonOrderedPostProcessors
,就是通常的處理器internalPostProcessors
,先排序後註冊ApplicationListenerDetector
的 processorDisposableBeanAdapter
和上文的BeanPostProcessor
的抽象層級不一樣,這個是和Bean綁定的,因此它的註冊時機是在Spring Bean的依賴注入階段,詳細源碼能夠看個人這篇文章Spring IoC 依賴注入 源碼解析。
源碼位置:AbstractAutowireCapableBeanFactory#doCreateBean()
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException {
// 省略前面的超多步驟,想了解的能夠去看源碼或者個人那篇文章
// Register bean as disposable.
// 這裏就是DisposableBeanAdapter的註冊步驟了
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()) {
// 註冊一個DisposableBean實現,該實現將執行給定bean的全部銷燬工做。
// 包括: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));
}
}
}
複製代碼
至此,Spring Bean的整個生命週期算是講解完了,從容器初始化到容器銷燬,以及回調事件的註冊時機等方面都說明了一下,但願能對你有所幫助。
本文由博客一文多發平臺 OpenWrite 發佈!