Spring中的DisposableBean和InitializingBean,ApplicationContextAware的用法
abbrlink: 3308881495 categories: Spring
Spring中的DisposableBean和InitializingBean的用法 在spring容器初始化bean和销毁bean的以前的操作有很多种, 目前我知道的有:在xml中定义的时候用init-method和destory-method,还有一种就是定义bean的时候实现DisposableBean和InitializingBean 这两个接口,打开InitializingBean 的源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public interface InitializingBean { /** * Invoked by a BeanFactory after it has set all bean properties supplied * (and satisfied BeanFactoryAware and ApplicationContextAware). * <p>This method allows the bean instance to perform initialization only * possible when all bean properties have been set and to throw an * exception in the event of misconfiguration. * @throws Exception in the event of misconfiguration (such * as failure to set an essential property) or if initialization fails. */ void afterPropertiesSet() throws Exception; }
根据注解很清楚的可以看出,afterPropertiesSet()表示在资源加载完以后,初始化bean之前执行的方法,我猜想spring底层应该会在初始化bean的时候,应该会使用(bean instanceof InitializingBean)判断是不是实现了这个接口,其实在很多框架中都是这么干的,但是因为没研究过spring源码,暂且还不知道底层原理。这样我们就可以在初始化的时候,做一些自己想要做的事了。 同理,DisposableBean就是在一个bean被销毁的时候,spring容器会帮你自动执行这个方法,估计底层原理也是差不多的,对于一些使用完之后需要释放资源的bean,我们都会实现这个接口,或者是配置destory-method方法。源码也基本是相似的,只是把afterPropertiesSet改为destroy。
ApplicationContextAware的用法 其实我们看到—Aware就知道是干嘛用的了,就是属性注入的,但是这个ApplicationContextAware的不同地方在于,实现了这个接口的bean,当spring容器初始化的时候,会自动的将ApplicationContext注入进来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 import org.apache.commons.lang.Validate; import org.springframework.beans.BeansException; import org.springframework.beans.factory.DisposableBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; /** * applicationContext静态化 * 使用了ApplicationContextAware接口的类,如果受spring容器管理的 * 话,那么就会自动的调用ApplicationContextAware中的setApplicationContext方法 * @author Hotusm * */ @Service @Lazy(false) public class SpringContextHolder implements ApplicationContextAware,DisposableBean{ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringContextHolder.applicationContext=applicationContext; } //清空applicationContext 设置其为null @Override public void destroy() throws Exception { SpringContextHolder.clearHolder(); } //获得applicationContext public static ApplicationContext getApplicationContext() { //assertContextInjected(); return applicationContext; } public static void clearHolder(){ applicationContext=null; } //获取Bean public static <T> T getBean(Class<T> requiredType){ //assertContextInjected(); return (T) getApplicationContext().getBean(requiredType); } @SuppressWarnings("unchecked") public static <T> T getBean(String name){ assertContextInjected(); return (T) getApplicationContext().getBean(name); } //判断application是否为空 public static void assertContextInjected(){ Validate.isTrue(applicationContext==null, "application未注入 ,请在springContext.xml中注入SpringHolder!"); } }
因为我们在做开发的时候,并不是说在每一个地方都能将属性注入到我们想要的地方去的,比如在Utils使用到dao,我们就不能直接注入了,这个时候就是我们需要封装springContext的时候了,而ApplicationContextAware就起了关键性的作用。
3:还有一种是注解的用法:
在指定方法上加上@PostConstruct或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用。
几种Bean初始化及销毁时定义操作方式的执行顺序 Spring 容器中的 Bean 是有生命周期的,Spring 允许 Bean 在初始化完成后以及销毁前执行特定的操作。下面是常用的三种指定特定操作的方法:
通过实现InitializingBean/DisposableBean 接口来定制初始化之后/销毁之前的操作方法; 通过 元素的 init-method/destroy-method属性指定初始化之后 /销毁之前调用的操作方法; 在指定方法上加上@PostConstruct或@PreDestroy注解来制定该方法是在初始化之后还是销毁之前调用。 这几种配置方式,执行顺序是怎样的呢?我们通过例子来研究下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.support.ClassPathXmlApplicationContext; public class InitAndDestroySeqBean implements InitializingBean,DisposableBean { public InitAndDestroySeqBean(){ System.out.println("执行InitAndDestroySeqBean: 构造方法"); } @PostConstruct public void postConstruct() { System.out.println("执行InitAndDestroySeqBean: postConstruct"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("执行InitAndDestroySeqBean: afterPropertiesSet"); } public void initMethod() { System.out.println("执行InitAndDestroySeqBean: init-method"); } @PreDestroy public void preDestroy() { System.out.println("执行InitAndDestroySeqBean: preDestroy"); } @Override public void destroy() throws Exception { System.out.println("执行InitAndDestroySeqBean: destroy"); } public void destroyMethod() { System.out.println("执行InitAndDestroySeqBean: destroy-method"); } public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("com/chj/spring/bean.xml"); context.close(); } }
Spring配置文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <context:annotation-config/> <bean id="initAndDestroySeqBean" class="com.chj.spring.InitAndDestroySeqBean" init-method="initMethod" destroy-method="destroyMethod"/> </beans>
运行InitAndDestroySeqBean的main方法,结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 2013-03-03 17:11:19,098 DEBUG support.DefaultListableBeanFactory - Creating instance of bean 'initAndDestroySeqBean' 执行InitAndDestroySeqBean: 构造方法 2013-03-03 17:11:19,114 DEBUG annotation.CommonAnnotationBeanPostProcessor - Found init method on class [com.alibaba.chj.spring.InitAndDestroySeqBean]: public void com.alibaba.chj.spring.InitAndDestroySeqBean.postConstruct() 2013-03-03 17:11:19,114 DEBUG annotation.CommonAnnotationBeanPostProcessor - Found destroy method on class [com.alibaba.chj.spring.InitAndDestroySeqBean]: public void com.alibaba.chj.spring.InitAndDestroySeqBean.preDestroy() 2013-03-03 17:11:19,129 DEBUG support.DefaultListableBeanFactory - Eagerly caching bean 'initAndDestroySeqBean' to allow for resolving potential circular references 2013-03-03 17:11:19,129 DEBUG annotation.CommonAnnotationBeanPostProcessor - Invoking init method on bean 'initAndDestroySeqBean': public void com.alibaba.chj.spring.InitAndDestroySeqBean.postConstruct() 执行InitAndDestroySeqBean: postConstruct 2013-03-03 17:11:19,129 DEBUG support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'initAndDestroySeqBean' 执行InitAndDestroySeqBean: afterPropertiesSet 2013-03-03 17:11:19,129 DEBUG support.DefaultListableBeanFactory - Invoking init method 'initMethod' on bean with name 'initAndDestroySeqBean' 执行InitAndDestroySeqBean: init-method 2013-03-03 17:11:19,129 DEBUG support.DefaultListableBeanFactory - Finished creating instance of bean 'initAndDestroySeqBean' 2013-03-03 17:11:19,129 INFO support.ClassPathXmlApplicationContext - Closing org.springframework.context.support.ClassPathXmlApplicationContext@56a499: display name [org.springframework.context.support.ClassPathXmlApplicationContext@56a499]; startup date [Sun Mar 03 17:11:17 CST 2013]; root of context hierarchy 2013-03-03 17:11:19,129 INFO support.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1292d26: defining beans [org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,initAndDestroySeqBean]; root of factory hierarchy 2013-03-03 17:11:19,129 DEBUG annotation.CommonAnnotationBeanPostProcessor - Invoking destroy method on bean 'initAndDestroySeqBean': public void com.alibaba.chj.spring.InitAndDestroySeqBean.preDestroy() 执行InitAndDestroySeqBean: preDestroy 2013-03-03 17:11:19,145 DEBUG support.DisposableBeanAdapter - Invoking destroy() on bean with name 'initAndDestroySeqBean' 执行InitAndDestroySeqBean: destroy 2013-03-03 17:11:19,145 DEBUG support.DisposableBeanAdapter - Invoking destroy method 'destroyMethod' on bean with name 'initAndDestroySeqBean' 执行InitAndDestroySeqBean: destroy-method
从执行结果可以看出: Bean在实例化的过程中:Constructor > @PostConstruct >InitializingBean > init-method
Bean在销毁的过程中:@PreDestroy > DisposableBean > destroy-method