浏览 6668 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-09-26
现在的问题是,由于需求是不断变化的,说不定哪天增加了一个又要在系统启动时往内存里面写点啥。此时,要么在原来的类的后面,加一段代码,要么就再写一个类,再配一个Listener。一般我会采用后面一种做法,因为这样至少可以做到对这些Listener保持可配置性,当业务发生变化时,简单改变配置文件就可以完成需求。不过这带来了一个问题,就是有可能web.xml就比较凌乱,而且还要搞清楚和其他一些系统启动运行的Listener的关系。 所以最近根据这个情况设计了一个简单的ServletContextLoader的装载器。在web.xml里面只需要配置一个Listener,而这个listener的作用就是依次按顺序调用其他的Listener。此时,其他的Listener都可以通过Spring的注入进入这个总的Listener服从调度。 /** * @author zhou.lu */ public class ServletContextLoaderListener implements ServletContextListener { private static final Log logger = LogFactory.getLog(ServletContextLoaderListener.class); private ServletContextLoader servletContextLoader; public void contextInitialized(ServletContextEvent event) { this.servletContextLoader = createServletContextLoader(event); this.servletContextLoader.initServletContext(event.getServletContext()); } private ServletContextLoader createServletContextLoader(ServletContextEvent event) { ApplicationContext applicationContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()); return (ServletContextLoader) applicationContext.getBean("servletContextLoader"); } public void contextDestroyed(ServletContextEvent event) { this.servletContextLoader.closeServletContext(event.getServletContext()); } } 这个就是一个总的Listener,这里模仿了Spring的源码,将具体的调度指派给ServletContextLoader这个接口来完成,而具体的实现则通过Spring拿到。接下来看一下它的具体实现: /** * @author zhou.lu */ public class ServletContextLoaderImpl implements ServletContextLoader, InitializingBean { private static final Log logger = LogFactory.getLog(ServletContextLoaderImpl.class); private List servletContextLoaders; public void setServletContextLoaders(List servletContextLoaders) { this.servletContextLoaders = servletContextLoaders; } public void afterPropertiesSet() throws Exception { for (int i = 0; i < servletContextLoaders.size(); i++) { // check every servletContextLoader and set to loaders Object loader = servletContextLoaders.get(i); if (!(loader instanceof ServletContextLoader)) { throw new IllegalArgumentException("Unsupported ServletContextLoader:" + loader.getClass()); } } } public void initServletContext(ServletContext servletContext) { for (int i = 0; i < servletContextLoaders.size(); i++) { ServletContextLoader loader = (ServletContextLoader) servletContextLoaders.get(i); loader.initServletContext(servletContext); } } public void closeServletContext(ServletContext servletContext) { for (int i = 0; i < servletContextLoaders.size(); i++) { ServletContextLoader loader = (ServletContextLoader) servletContextLoaders.get(i); loader.closeServletContext(servletContext); } } } 其实这个具体的实现就是做了所有的调度。而所有实现ServletContextLoader这个接口,并且被注入到这个类中去的ServletContextLoader会被依次执行其中的方法。因而,所以如果以后要做系统启动时的数据加载,只要简单实现ServletContextLoader这个接口,并且配置到Spring的配置文件中即可。例如: public class MasterDataLoader implements ServletContextLoader { private SystemService systemService; public void initServletContext(ServletContext servletContext) { // Master Data Loader Map masterData = systemService.getMasterData(); // TODO Add to servletContext } public void closeServletContext(ServletContext servletContext) { // TODO Clear servletContext } public void setSystemService(SystemService systemService) { this.systemService = systemService; } } 然后是Spring的配置文件片断: <bean id="systemService" parent="baseTxProxy"> <property name="target"> <bean class="com.adt.surecenter.service.impl.SystemServiceImpl" autowire="byName"/> </property> </bean> <bean id="commandMappingLoader" class="com.adt.surecenter.loader.CommandMappingLoader" autowire="byName" /> <bean id="masterDataLoader" class="com.adt.surecenter.loader.MasterDataLoader" autowire="byName" /> <bean id="servletContextLoader" class="com.adt.core.loader.ServletContextLoaderImpl" autowire="byName" > <property name="servletContextLoaders"> <list> <ref bean="masterDataLoader"/> </list> </property> </bean> 最后别忘记在web.xml中配置最初写的那个Listener,并且放置在Spring的Listener之后,就ok了。 <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>com.adt.core.loader.ServletContextLoaderListener</listener-class> </listener> 此时,你在web.xml中的配置简化了,你所需要实现的具体的每个servletContextLoader看上去就像一个POJO,实现某个接口,收到Spring的管理,遵循Spring的IoC。 好了,收工,洗手。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-09-26
既然你都和spring绑定到一起用了,为啥还需要listener呢?
在某个setup bean的afterPropertiesSet() 方法里面做初始化的动作不就OK了吗? 如果没有spring,也可以在web.xml里面配置context-param,多设置几个setup bean的class name,然后统一由一个Listener读入不也OK吗? |
|
返回顶楼 | |
发表时间:2006-09-26
Readonly 写道 既然你都和spring绑定到一起用了,为啥还需要listener呢?
在某个setup bean的afterPropertiesSet() 方法里面做初始化的动作不就OK了吗? 如果没有spring,也可以在web.xml里面配置context-param,多设置几个setup bean的class name,然后统一由一个Listener读入不也OK吗? 一开始是考虑如果初始化过程无论有数据库读还是写操作,想用到Spring的事务管理。 不过你说得对,既然和Spring绑在一起了,就在afterPropertiesSet()方法里面做初始化动作好了。一开始没想到,脑子进水了。搞得那么麻烦,回去改掉。 |
|
返回顶楼 | |