想要實現的功能: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來管理,也沒有效果。
如果有其它的辦法請分享給我,謝謝!!