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