1. 通過(guò)ApplicationContextAware 2. 通過(guò)WebApplicationContext 外部系統 訪(fǎng)問(wèn)已初始化的spring實(shí)例, 目前找到兩種方法 1. 通過(guò)ApplicationContextAware 2. 通過(guò)WebApplicationContext 先介紹一點(diǎn)需求。 業(yè)務(wù)系統要和gis系統進(jìn)行集成,本來(lái)是分來(lái)的兩個(gè)war包通過(guò)Web Service調用, 現在要合到一個(gè)war中,一起部署。業(yè)務(wù)系統使用的架構是以spring基礎,struts+ibatis+xfire。 GIS的架構,主要是jsf, arc-gis (對這部分不太了解)。 現在GIS系統需要調用業(yè)務(wù)系統的數據,既然兩個(gè)系統現在準備合成一個(gè)系統,Web Service的方式肯定是一種不太可取的方法,本地調用才有保證效率。 但是,問(wèn)題出在了GIS系統,不是按照spring架構的IOC方式注入的?,F在需要開(kāi)一個(gè)口,給GIS系統spring的全局Context,可以讓 GIS不通過(guò)IOC也可以得到beans。昨天試了一下,Spring支持這種外來(lái)的功能,目前發(fā)現了兩種辦法。不過(guò)這兩種辦法,都存在著(zhù)風(fēng)險,后面會(huì )說(shuō)到。 1. 通過(guò)ApplicationContextAware。寫(xiě)一個(gè)子類(lèi),實(shí)現ApplicationContextAware的方法,然后把這個(gè)類(lèi)配置到Spring容器中。啟動(dòng)的時(shí)候,容器會(huì )自動(dòng)調用setApplicationContext的方法, 把容器全局的context給傳進(jìn)來(lái), 賦值給靜態(tài)變量ctx。然后,非spring模塊,想調用spring容器實(shí)例的時(shí)候,可以直接通過(guò)SetSpringContext .getCtx(); 獲得這個(gè)context。 因此,方法不依賴(lài)于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; } } ------------------------------------------------------------------------------------------------------------------ 風(fēng)險: 1) 由于spring中的單例和Gof所描述的單例不一樣。因此,其實(shí)applicationContext是代碼級非單例的,把非靜態(tài)的對象給一個(gè)靜態(tài)對象,這是不安全的。 2) 由于把整個(gè)的spring全局實(shí)例,對外暴露,因此給了其他系統,可以修改spring容器全局變量的功能,容易受到惡意篡改,或者安全的漏洞。 2. 通過(guò)WebApplicationContext。這種方法的出發(fā)點(diǎn),是兩個(gè)工程在一個(gè)war包里面,因此ServletContext是全局共享的。調用 WebApplicationContextUtils.getWebApplicationContext(getServletContext()); 傳一個(gè)ServletContext, 然后獲得WebApplcationContext的全局實(shí)例, 再把這個(gè)實(shí)例子,傳給一個(gè)靜態(tài)變量,給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> * 容器起動(dòng)的時(shí)候,加載這個(gè)servlet。 */ public void init(){ WebApplicationContext wac =WebApplicationContextUtils.getWebApplicationContext(getServletContext()); SpringDTO.setCtx(wac); } public void doGet(HttpServletRequest request, HttpServletResponse response) { // wac =WebApplicationContextUtils.getWebApplicationContext(getServletContext()); } } 中間的類(lèi): 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); } } 中間的類(lèi): 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; } } 調用的類(lèi): 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(); } } } ---------------------------------------------------------- 風(fēng)險: 1. 與第一種方法一樣,都是給外部一個(gè)static變量,把全局的spring實(shí)例給外部用。 2. 這種方式,外部調用的時(shí)候必需依賴(lài)與Servlet,并且得到的是Spring Context的子類(lèi)。 目前來(lái)看,第一種方式,比第二更靈活,但風(fēng)險更大。 更進(jìn)一步的論證,或者其他的用法,還待后面的繼續開(kāi)發(fā),測試中。 |