Spring扩展接口BeanFactoryAware,InitializingBean,DisposableBean与bean的生命周期
一、介绍
从一张spring经典bean的生命周期图说起:

接口介绍:
- xxAware接口:包含常见的BeanFactoryAware、BeanFactoryAware、ApplicationContextAware
- BeanPostProcessor接口:方法postProcessBeforeInitialization()、postProcessAfterInitialization(),用于在bean初始化时进行前置、后置处理。
- InitializingBean接口:方法afterPropertiesSet(),顾名思义在Properties配置文件初始化之后调用。
- DisposableBean接口:方法destroy(),bean的生命周期结束前调用。
- init-method方法:初始化方法
- destroy方法:销毁方法
二、示例
这里整一个demo,如下所示:
BeanFactoryAware,InitializingBean,DisposableBean接口实现类:
1 public class SpringStartTestBean implements BeanFactoryAware,InitializingBean,DisposableBean { 2 3 @Override 4 public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 5 System.out.println("BeanFactoryAware.setBeanFactory() running"); 6 } 7 8 @Override 9 public void destroy() throws Exception { 10 System.out.println("DisposableBean.destroy() running"); 11 } 12 13 @Override 14 public void afterPropertiesSet() throws Exception { 15 System.out.println("InitializingBean.afterPropertiesSet() running"); 16 } 17 18 public void initMethod(){ 19 System.out.println("initMethod() running"); 20 } 21 22 public void destroyMethod(){ 23 System.out.println("destroyMethod() running"); 24 } 25 }
BeanPostProcessor接口实现类:
1 public class TestBeanPostProcessor implements BeanPostProcessor { 2 @Override 3 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 4 System.out.println("BeanPostProcessor.postProcessBeforeInitialization() running|beanName="+beanName); 5 return null; 6 } 7 8 @Override 9 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 10 System.out.println("BeanPostProcessor.postProcessAfterInitialization() running|beanName="+beanName); 11 return null; 12 } 13 }
spring配置文件:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName"> <bean id="stringStartTest" class="com.spring.test.SpringStartTestBean" init-method="initMethod" destroy-method="destroyMethod"/> <bean id="testBeanPostProcessor" class="com.spring.test.TestBeanPostProcessor" /> </beans>
注:这里可能有小伙伴会问,为什么BeanPostProcessor接口要单独整一个实现类,用第一个类不可以吗?这是因为BeanPostProcessor接口实现类是所有bean共有的,每个bean初始化前后都会调BeanPostProcessor实现类的方法,因此放到某个具体的bean中都不合适。
启动类:
1 public class Test { 2 3 public static void main(String[] args) { 4 ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml"); 5 ((ClassPathXmlApplicationContext) context).close(); 6 } 7 8 }
运行结果:

可见,实现的各个接口方法调用顺序符合原图。
注:
- destroy-method一般作为DisposableBean.destory()方法的替代,二者功能等效,因为DisposableBean.destory()接口实现依赖于Spring,为与Spring解耦可以用destroy-method;
- 两个destroy()方法运行有两个前提:
- context关闭,如我们实例中的((ClassPathXmlApplicationContext) context).close();
- bean的scope为singleton,即spring只销毁单例的bean
三、源码分析
1、bean的创建
前面的跳过,直接通过refash()方法往下调用:
ApplicationContext.refresh()
->ApplicationContext.registerBeanPostProcessors()
->PostProcessorRegistrationDelegate.registerBeanPostProcessors()
->AbstractBeanFactory.getBean()->......
->AbstractAutowireCapableBeanFactory.initializeBean()

在AbstractAutowireCapableBeanFactory.initializeBean()方法中:

如上所示:
invokeAwareMethods()方法调用各个xxAware接口的实现方法,然后调用BeanPostProcessor接口实现的postProcessBeforeInitialization()方法,继而调用init-method指定的方法,最后调用BeanPostProcessor接口实现的postProcessAfterInitialization()方法.
而InitializingBean的接口实现方法调用是在方法invokeInitMethod()中,调用init-method之前:

2、bean的销毁
spring中bean的销毁由context的销毁触发的,我们从ClassPathXmlApplicationContext.close()方法进入:
AbstractApplicationContext.close()
->AbstractApplicationContext.doClose()
->AbstractApplicationContext.destroyBeans()
->DefaultListableBeanFactory.destroySingletons()
->DefaultListableBeanRegistry.destroySingletons()
->DefaultListableBeanRegistry.destroySingleton()
->DefaultListableBeanRegistry.destroyBean()
->DisposableBeanAdapter.destroy()
在DisposableBeanAdapter.destroy()方法中:
1 @Override 2 public void destroy() { 3 if (!CollectionUtils.isEmpty(this.beanPostProcessors)) { 4 for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) { 5 processor.postProcessBeforeDestruction(this.bean, this.beanName); 6 } 7 } 8 9 if (this.invokeDisposableBean) { 10 if (logger.isTraceEnabled()) { 11 logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'"); 12 } 13 try { 14 if (System.getSecurityManager() != null) { 15 AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> { 16 ((DisposableBean) this.bean).destroy(); 17 return null; 18 }, this.acc); 19 } 20 else { 21 ((DisposableBean) this.bean).destroy();//调用DisposableBean接口实现类的destroy()方法 22 } 23 } 24 catch (Throwable ex) { 25 String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'"; 26 if (logger.isDebugEnabled()) { 27 logger.warn(msg, ex); 28 } 29 else { 30 logger.warn(msg + ": " + ex); 31 } 32 } 33 } 34 35 if (this.destroyMethod != null) { 36 invokeCustomDestroyMethod(this.destroyMethod);//调用destory-Method指定的销毁方法 37 } 38 else if (this.destroyMethodName != null) { 39 Method methodToInvoke = determineDestroyMethod(this.destroyMethodName); 40 if (methodToInvoke != null) { 41 invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke)); 42 } 43 } 44 }
其中,第21行调用了DisposableBean接口实现类的destroy()方法,第36行调用了destroy-method指定的销毁方法。
四、拓展
在spring中我们可以手动调用xxApplicationContext.close()或xxBeanFactory.destroySingletons()来销毁单例的bean,但是如果在web容器或EJB容器中该如何销毁这些bean呢?直接调用xxApplicationContext.close()或xxBeanFactory.destroySingletons(),这可不够丝滑。
javax.servlet-api包已经为web容器准备好了,实现ServletContextListener接口:
1 public interface ServletContextListener extends EventListener { 2 3 public void contextInitialized(ServletContextEvent sce); 4 5 public void contextDestroyed(ServletContextEvent sce); 6 7 }
可见,该接口只提供了两个方法:
contextInitialized():完成context初始化
contextDestroyed():完成context销毁
其中,context.close操作可以封装在contextDestroyed()方法的实现中。
在spring-web包中,已经提供了实现类ContextLoaderListener感兴趣的小伙伴可以看看具体实现。
1 public class ContextLoaderListener extends ContextLoader implements ServletContextListener { 2 3 public ContextLoaderListener() { 4 } 5 6 public ContextLoaderListener(WebApplicationContext context) { 7 super(context); 8 } 9 10 @Override 11 public void contextInitialized(ServletContextEvent event) { 12 initWebApplicationContext(event.getServletContext()); 13 } 14 15 16 /** 17 * Close the root web application context. 18 */ 19 @Override 20 public void contextDestroyed(ServletContextEvent event) { 21 closeWebApplicationContext(event.getServletContext()); 22 ContextCleanupListener.cleanupAttributes(event.getServletContext()); 23 } 24 25 }
注:文中spring源码基于5.2.8.RELEASE

浙公网安备 33010602011771号