spring在web容器啓動時執行初始化方法

需求:在tomcat啓動時開啓一個定時任務。 java

想法:容器啓動時執行方法,最容易想到的就是servlet中能夠配置load-on-startup,設置一個正整數也就能夠隨容器一塊兒啓動。 spring

問題:上面的方法很好,可是因爲定時任務須要去操做數據庫,而項目採用了spring的依賴注入來管理對象,而servlet並不受Spring的管理。若此時在servlet中注入Spring管理的對象,則會報錯:javax.naming.NameNotFoundException: Name com.test.InitServlet is not bound in this Context。 數據庫

因此想要再servlet中操做數據庫,只能手動去建立一個service,這顯然違背了咱們使用Spring的初衷,讓項目看起來不三不四的。那麼如何才能在啓動WEB容器的時候執行一段初始化代碼,而且可讓其被Spring管理呢? tomcat

解決方案:Spring提供了當一個Bean初始化後執行方法的擴展點:InitializingBean。這裏的初始化指的就是當該Bean的屬性被注入完成後(注意:這裏並非全部屬性都須要被設置),因此InitializingBean接口提供的方法名稱也很形象:afterPropertiesSet()。 ide

使用的時,將該Bean注入到Spring容器,以後咱們即可以得到Spring容器中的對象了,也就是說,能夠獲得service方法來執行咱們的定時任務了。 ui

具體代碼以下: this

[java]  view plain copy
  1. @Component  
  2. public class InitServlet implements InitializingBean {  
  3.   
  4.     /** 
  5.      *  
  6.      */  
  7.     private static final long serialVersionUID = 1L;  
  8.       
  9.     @Resource   
  10.     private DispatchesService dispatchesService;  
  11.   
  12.     @Override  
  13.     public void afterPropertiesSet() throws Exception {  
  14.     <span style="white-space:pre">    </span>dispatchesService.spyDDetails();  
  15.     }  
  16.   
  17. }  

另外還有兩種方法也能夠實現如上的功能。 spa

一、若採用XML來配置Bean的話,能夠指定屬性init-method .net

二、經過註解@PostConstruct來修改初始化方法 debug

值得注意的是,三者能夠同時存在,觸發的順序是先觸發@PostConstruct修飾的方法,再觸發afterPropertiesSet(),最後觸發init-method

其中@PostConstruct是經過註冊一個BeanPostProcessor,在Bean的初始化方法以前調用,而afterPropertiesSet()和init-method都在初始化方法中調用

關於@PostConstruct詳細的介紹能夠看這裏:http://blog.csdn.net/yaerfeng/article/details/8447530

下面是Spring中調用Bean的初始化代碼的源代碼:

[java]  view plain copy
  1.     protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)  
  2.             throws Throwable {  
  3.   
  4.         boolean isInitializingBean = (bean instanceof InitializingBean);  
  5.         if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {  
  6.             if (logger.isDebugEnabled()) {  
  7.                 logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");  
  8.             }  
  9.             if (System.getSecurityManager() != null) {  
  10.                 try {  
  11.                     AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
  12.                         public Object run() throws Exception {  
  13.                             ((InitializingBean) bean).afterPropertiesSet();<span style="white-space:pre"> </span><span style="font-family: Arial, Helvetica, sans-serif;">// 這裏觸發afterPropertiesSet</span><span style="white-space:pre">  
  14. </span>  
  15.                             return null;  
  16.                         }  
  17.                     }, getAccessControlContext());  
  18.                 }  
  19.                 catch (PrivilegedActionException pae) {  
  20.                     throw pae.getException();  
  21.                 }  
  22.             }                 
  23.             else {  
  24.                 ((InitializingBean) bean).afterPropertiesSet();<span style="white-space:pre"> </span>// 這裏觸發afterPropertiesSet  
  25.             }  
  26.         }  
  27.   
  28.         if (mbd != null) {  
  29.             String initMethodName = mbd.getInitMethodName();// 這裏是觸發init-method  
  30.             if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&  
  31.                     !mbd.isExternallyManagedInitMethod(initMethodName)) {  
  32.                 invokeCustomInitMethod(beanName, bean, mbd);  
  33.             }  
  34.         }  
  35.     }  


補充:

還有一種方法,是當Spring將全部的Bean都初始化完成後,會留給咱們一個入口,咱們能夠實現以下接口

[java]  view plain copy
  1. @Component  
  2. public class InstantiationTracingBeanPostProcessor implements  
  3.         ApplicationListener<ContextRefreshedEvent> {  
  4.   
  5.     @Override  
  6.     public void onApplicationEvent(ContextRefreshedEvent arg0) {  
  7.         System.out.println("-----全部Bean載入完成---");  
  8.     }  
  9. }  
相關文章
相關標籤/搜索