1. 通过ApplicationContextAware 2. 通过WebApplicationContext
外部系统 访问已初始化的spring实例, 目前找到两种方法 1. 通过ApplicationContextAware 2. 通过WebApplicationContext
先介绍一点需求。 业务系统要和gis系统进行集成,本来是分来的两个war包通过Web Service调用, 现在要合到一个war中,一起部署。业务系统使用的架构是以spring基础,struts+ibatis+xfire。 GIS的架构,主要是jsf, arc-gis (对这部分不太了解)。 现在GIS系统需要调用业务系统的数据,既然两个系统现在准备合成一个系统,Web Service的方式肯定是一种不太可取的方法,本地调用才有保证效率。
但是,问题出在了GIS系统,不是按照spring架构的IOC方式注入的。现在需要开一个口,给GIS系统spring的全局Context,可以让 GIS不通过IOC也可以得到beans。昨天试了一下,Spring支持这种外来的功能,目前发现了两种办法。不过这两种办法,都存在着风险,后面会说到。
1. 通过ApplicationContextAware。写一个子类,实现ApplicationContextAware的方法,然后把这个类配置到Spring容器中。启动的时候,容器会自动调用setApplicationContext的方法, 把容器全局的context给传进来, 赋值给静态变量ctx。然后,非spring模块,想调用spring容器实例的时候,可以直接通过SetSpringContext .getCtx(); 获得这个context。 因此,方法不依赖于servlet。
-------------------------------------------------------------------------------------------------------- package com.dvs.test;
import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware;
public class SetSpringContext implements ApplicationContextAware{ private static ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.ctx = applicationContext; }
public static ApplicationContext getCtx() { return ctx; }
public static void setCtx(ApplicationContext ctx) { SetSprContext.ctx = ctx; }
} ------------------------------------------------------------------------------------------------------------------
风险: 1) 由于spring中的单例和Gof所描述的单例不一样。因此,其实applicationContext是代码级非单例的,把非静态的对象给一个静态对象,这是不安全的。 2) 由于把整个的spring全局实例,对外暴露,因此给了其他系统,可以修改spring容器全局变量的功能,容易受到恶意篡改,或者安全的漏洞。
2. 通过WebApplicationContext。这种方法的出发点,是两个工程在一个war包里面,因此ServletContext是全局共享的。调用 WebApplicationContextUtils.getWebApplicationContext(getServletContext()); 传一个ServletContext, 然后获得WebApplcationContext的全局实例, 再把这个实例子,传给一个静态变量,给Servlet调用。
-------------------------------------------------------- package com.dvs.test;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils;
public class GetSpringContext extends HttpServlet { /** * <servlet> * <servlet-name>GetSpringContext</servlet-name> * <servlet-class>com.dvs.test.GetSpringContext</servlet-class> * <load-on-startup>1</load-on-startup> * </servlet> * 容器起动的时候,加载这个servlet。 */ public void init(){ WebApplicationContext wac =WebApplicationContextUtils.getWebApplicationContext(getServletContext()); SpringDTO.setCtx(wac); } public void doGet(HttpServletRequest request, HttpServletResponse response) { // wac =WebApplicationContextUtils.getWebApplicationContext(getServletContext()); } }
中间的类: package com.dvs.test;
import org.springframework.web.context.WebApplicationContext;
/** * @author Conan * */ public class GetSpringContextFactory<E> {
public E getBean(String name) { WebApplicationContext wac = SpringDTO.getCtx(); return (E) wac.getBean(name); }
}
中间的类: package com.dvs.test;
import org.springframework.web.context.WebApplicationContext;
public class SpringDTO { private static WebApplicationContext ctx;
public static WebApplicationContext getCtx() { return ctx; }
public static void setCtx(WebApplicationContext ctx) { SprFactory.ctx = ctx; }
}
调用的类: package com.dvs.test;
import java.util.List;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import com.dvs.sec.model.usergroup.UserGroupDTO; import com.dvs.sec.service.usergroup.UserGroupService;
public class TestSpring extends HttpServlet{ public void doGet(HttpServletRequest request, HttpServletResponse response) { test(); }
public void test(){ GetSpringContextFactory ctx = new GetSpringContextFactory(); UserGroupService ug = (UserGroupService) ctx.getBean("userGroupService"); try { List<UserGroupDTO> list= ug.getUserGroupList(); for(UserGroupDTO dto:list){ System.out.println(dto.getPk()); } } catch (Exception e) { e.printStackTrace(); } } }
---------------------------------------------------------- 风险: 1. 与第一种方法一样,都是给外部一个static变量,把全局的spring实例给外部用。 2. 这种方式,外部调用的时候必需依赖与Servlet,并且得到的是Spring Context的子类。
目前来看,第一种方式,比第二更灵活,但风险更大。
更进一步的论证,或者其他的用法,还待后面的继续开发,测试中。
|