Spring初始化完成后直接執行一個方法,初始化數據(解決方法被重復執行兩次的情況)


在做WEB項目時,經常在項目第一次啟動時利用WEB容器的監聽、Servlet加載初始化等切入點為數據庫准備數據,這些初始化數據 是系統開始運行前必須的數據,例如權限組、系統選項、默認管理員等等。但是項目若不是WEB工程,或者說還沒用到WEB層(例如單元測試),這時應如何方 便地初始化數據呢?

    借助Spring容器是個很好的解決方案。Spring框架提供了事件機制,而事件機制必須實現ApplicationListener監聽器,因此我們 只要編寫一個實現類實現該接口的onApplicationEvent方法,在方法體中檢測數據庫的初始化數據是否存在並選擇初始化之。

 

第一步:定義一個類InitData實現ApplicationListener

 

  1. import java.util.HashMap;  
  2. import java.util.Map;  
  3.   
  4. import org.apache.commons.logging.Log;  
  5. import org.apache.commons.logging.LogFactory;  
  6. import org.springframework.context.ApplicationEvent;  
  7. import org.springframework.context.ApplicationListener;  
  8. import org.springframework.stereotype.Controller;  
  9.   
  10. import com.ebay.cloud.cms.typsafe.metadata.model.MetaClass;  
  11. import com.ebay.tools.cms.exception.UtilityException;  
  12. import com.ebay.tools.cms.util.CommonInterfaceUtility;  
  13. import com.ebay.tools.cms.util.ExceptionUtils;  
  14. import com.ebay.tools.cms.util.LoggerUtil;  
  15.   
  16. /** 
  17.  * @author Josh Wang(Sheng) 
  18.  * @email swang6@email.com 
  19.  *  
  20.  * This class used to initialize data / load data ON the application started  
  21.  */  
  22. @Controller  
  23. public class InitData implements ApplicationListener<ApplicationEvent> {  
  24.       
  25.     private Log logger = LogFactory.getLog(InitData.class);  
  26.       
  27.     private static boolean isStart = false;  
  28.   
  29.     private static Map<String, MetaClass> cmsMetas = new HashMap<String, MetaClass>();  
  30.   
  31.     public void onApplicationEvent(ApplicationEvent event) {  
  32.         if (!isStart) {  
  33.             isStart = true;  
  34.             LoggerUtil.info(logger, "Start to load CMS Meta data");  
  35.               
  36.             try {  
  37.                 cmsMetas = CommonInterfaceUtility.getMetaClass();  
  38.             } catch (UtilityException e) {  
  39.                 LoggerUtil.error(logger, "Load Meta Class failed" + ExceptionUtils.getStackTraceMsg(e));  
  40.             }  
  41.               
  42.             LoggerUtil.info(logger,"End to load CMS Meta data");  
  43.               
  44.             LoggerUtil.info(logger,"Start to load Other data");  
  45.               
  46.             LoggerUtil.info(logger,"End to load Other data");  
  47.         }  
  48.           
  49.     }  

 第二步:解決onApplicationEvent(方法被執行兩次以上的問題:

原因:

      在web 項目中(spring mvc),系統會存在兩個容器,一個是root application context ,另一個就是我們自己的 projectName-servlet  context(作為root application context的子容器)。 這種情況下,就會造成onApplicationEvent方法被執行兩次。

 

解決方法:

      如代碼所示,只需要使用一個類變量isStart即可。

 

需要注意的是,一定要加Annotation @Controller,這樣才表示是一個Spring的Bean(否則在相關Spring的xml中配置),才能被Spring容器處理。

 

第三步,寫一個Spring JunitTest,注意相關的Annotation

需要注意的就是在類上面加入如下兩個Annotation即可:

@ContextConfiguration(locations = "file:../validator-web/src/main/webapp/WEB-INF/cms-validator-servlet.xml")

@RunWith(SpringJUnit4ClassRunner.class)

 

@ContextConfiguration用於加載spring的核心配置文件,因為這個操作是一個公共的操作,所以我們常常可以寫在一個BaseTest中。

  1. @ContextConfiguration(locations = "file:../validator-web/src/main/webapp/WEB-INF/cms-validator-servlet.xml")  
  2. public class BaseTest {  
  3.   
  4.     /** 
  5.      * Set up the environment 
  6.      * @throws Exception 
  7.      */  
  8.     @BeforeClass  
  9.     public static void setUp() throws Exception {  
  10.                  
  11.     }  
  12.       
  13.     public static void print(String message) {  
  14.         System.out.println(message);  
  15.     }  
  16.   
  17.     public static void printHighlight(String message) {  
  18.         System.err.println(message);  
  19.     }  
  20.   
  21. }  

 

然后只需要在你的測試類上用這個Annotation:@RunWith(SpringJUnit4ClassRunner.class)

  1. @RunWith(SpringJUnit4ClassRunner.class)  
  2. public class TestCacheUtil extends BaseTest {  
  3.   
  4.     @Test  
  5.     public void getCMSMetaAttributeType() throws UtilityException {  
  6.   
  7.     }  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM