ssh下:系統初始化實現ServletContextListener接口時,獲取spring中數據層對象無效的問題


想要實現的功能:SSH環境下,數據層都交由Spring管理;在服務啟動時,將數據庫中的一些數據加載到ServletContext中緩存起來。

 

系統初始化類需要實現兩個接口:

ServletContextListener,系統初始化時調用contextInitialized方法緩存數據;

ApplicationContextAware,獲取Spring的ApplicationContext對象,以獲取spring容器管理的service對象。

系統初始化類如下:

 1 package com.lizhou.action;  2 
 3 import java.util.List;  4 
 5 import javax.servlet.ServletContext;  6 import javax.servlet.ServletContextEvent;  7 import javax.servlet.ServletContextListener;  8 
 9 import org.springframework.beans.BeansException; 10 import org.springframework.context.ApplicationContext; 11 import org.springframework.context.ApplicationContextAware; 12 import org.springframework.stereotype.Component; 13 
14 import com.lizhou.entity.ProductBigType; 15 import com.lizhou.service.inter.ProductBigTypeServiceInter; 16 
17 /**
18  * 初始化:實現application緩存數據功能 19  * 在服務啟動時,將數據庫中的數據加載進內存 20  * @author bojiangzhou 21  * 22  */
23 @Component //這里要該注解,不然無法注入ApplicationContext對象
24 public class InitAction implements ServletContextListener, ApplicationContextAware { 25     
26     private ApplicationContext ac; 27     
28  @Override 29     public void contextInitialized(ServletContextEvent event) { 30         //這里輸出當前調用該方法的對象
31         System.out.println("contextInitialized: "+this); 32         
33         //獲取application
34         ServletContext application = event.getServletContext(); 35         //獲取服務層
36         ProductBigTypeServiceInter bigTypeService = (ProductBigTypeServiceInter) this.ac.getBean("bigTypeService"); 37         //獲取商品大類集合
38         List<ProductBigType> bigTypeList = bigTypeService.findAllBigTypeList(); 39         //保存到application緩存中
40         application.setAttribute("bigTypeList", bigTypeList); 41  } 42     
43  @Override 44     public void setApplicationContext(ApplicationContext ac) throws BeansException { 45         //這里輸出當前調用該方法的對象
46         System.out.println("setApplicationContext: "+this); 47         this.ac = ac; 48  } 49     
50  @Override 51     public void contextDestroyed(ServletContextEvent event) { 52  } 53 
54 }

 

下面是web.xml里spring和系統初始化的配置:spring是在系統初始化類前加載的

 1 <!-- 添加對spring的支持 -->
 2   <context-param>
 3       <param-name>contextConfigLocation</param-name>
 4       <param-value>classpath:applicationContext.xml</param-value>
 5   </context-param>
 6   
 7   <!-- 定義spring的監聽器,加載spring -->
 8   <listener>
 9       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
10   </listener>
11   
12   <!-- 添加自己的初始化action -->
13   <listener>
14       <listener-class>com.lizhou.action.InitAction</listener-class>
15   </listener>

 

 

服務啟動時,控制台輸出如下信息:

 

首先,從輸出的信息來看,ApplicationContext對象已經注入進來了;

但是,第36行,也就是通過ApplicationContext來獲取服務層對象時報錯空指針異常了,說明ApplicationContext為空;

造成這個異常的原因很明顯:從輸出的兩個對象來看,調用setApplicationContext方法和contextInitialized方法不是同一個對象,所以在調用contextInitialized方法時,ApplicationContext還是為Null;

因為調用setApplicationContext方法的對象是由Spring初始化的,而調用contextInitialized方法的對象是由tomcat在加載web.xml時通過反射創建的。

所以兩個對象不一致。

 

這里我想到一種解決辦法是:將ApplicationContext設置為靜態的(static),這樣就只有一個ApplicationContext對象了。

 1 private static ApplicationContext ac; //設置為靜態 

這樣就不會報空指針異常了。一切就OK了!

 

想了想,好像不能將這個初始化類交給Spring來管理,它配置在web.xml中,系統啟動時就會觸發ServletContextEvent事件,然后調用contextInitialized方法來做初始化工作,它是由tomcat來完成的。即使交由Spring來管理,也沒有效果。

如果有其它的辦法請分享給我,謝謝!!

 


免責聲明!

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



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