标签:
---恢复内容开始---
问题:在一个web应用中我使用了spring框架,但有一部分模块或组件并没有托管给Spring,比如有的可能是一个webservice服务类,如果我想在这些非托管的类里使用托管对象该怎么办呢,很自然的我们需要获得spring容器对象的引用ApplicationContext,我的想法是在服务启动后,想办法将ApplicationContext容器的应用保存到一个静态变量中,以后使用就简单了。
1)刚开始用的是spring+struts2,实力话spring用的是ContextLoaderListener,如下
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/conf/comm/applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
这种情况下通过写一个listener,在web.xml配置在spring的实例化之后就行,在contextInitialized方法中保存spring容器
public class ApplicationContextListener implements ServletContextListener{ public void contextDestroyed(ServletContextEvent arg0) { } public void contextInitialized(ServletContextEvent event) { C.wac = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()); System.out.println("存储spring 容器结束:ApplicationContext="+C.wac); } }
2)今天写一个新项目,想尝试一下spring mvc,边学边做,第一件事自然是将spring+struts2中的一些东西以spring mvc的方式映射过来,哪不会学哪,自然保存spring容器的引用成为了其中一项映射工作,因为spring mvc的初始化用的是一个servlet(DispatcherServlet),所以不可能再用listener来保存容器(实例化顺序listener -> filter -> servlet),刚开始想的是用servlet,通过配置<load-on-startup>控制servlet的实例化在spring的servlet之后,但不知为什么就是无法获得spring容器,一直报空指针异常。最后没办法只能放弃。只能换思路了,在网上找到一个ApplicationContextAware接口,实现该接口的托管对象在被实例化时spring会通过setApplicationContext方法将ApplicationContext对象传入这和struts2中SessionAware等的设计是一样的,测试可以获得spring容器对象的引用,如下(这里有点小知识,spring在启动时对于单例对象会直接实例化,所以配置该对象时不用设置Scope,采用默认即可)
@Component public class InitComponent implements ApplicationContextAware{ @Override public void setApplicationContext(ApplicationContext ac) throws BeansException { //存储spring容器引用 C.wac = ac; } }
3)通过实现ApplicationContextAware已能获得容器引用,但有一个问题,如果你希望在spring容器实例化完做点事,比如启动一个维护线程做点维护工作,该工作可能要用到spring容器里的东东。则上面的方法并不能保证你获得spring容器引用时spring容器已初始化完毕。进一步搜搜搜发现spring提供了一些事件监听
spring提供了内置的几类的事件:ContextClosedEvent 、ContextRefreshedEvent(spring实例化完) 、ContextStartedEvent(spring实例化之前) 、ContextStoppedEvent(spring销毁后) 、RequestHandleEvent
其中的ContextRefreshedEvent正式我们需要的,在spring容器启动完成后会触发ContextRefreshedEvent事件,监听方法如下,实现
ApplicationListener,泛型参数传ContextRefreshedEvent,对于其它事件的监听类似
@Component public class InitListener implements ApplicationListener<ContextRefreshedEvent>{ @Override public void onApplicationEvent(ContextRefreshedEvent e) { WebApplicationContext wac = (WebApplicationContext)e.getApplicationContext(); //存储spring容器引用 C.wac = wac; System.out.println(C.wac); //存储配置文件路径 C.CONF_PATH = wac.getServletContext().getRealPath("/WEB-INF/conf"); System.out.println(C.CONF_PATH); //初始化log4j PropertyConfigurator.configure(C.CONF_PATH+"/comm/log4j.properties"); //启动系统缓存 C.wac.getBean(CacheManager.class).start(); } }
---恢复内容结束---
Spring--------web应用中保存spring容器
标签:
原文地址:http://www.cnblogs.com/jay-blog/p/4480385.html