阿里巴巴长期招聘Java研发工程师p6,p7,p8等上不封顶级别,有意向的可以发简历给我,注明想去的部门和工作地点:1064454834@qq.com
欢迎关注微信公众号:技术原始积累 获取更多技术干货
一、前言
一个项目随着业务增长,模块的增多,模块间的相互依赖,相互引用,使得项目结构越来越复杂,目前我们使用webx时候虽然分为了一个个模块,但是模块间的bo还是可以随意调用,比如模块A可以调用模块B的bo,那么模块间的耦合度就大大的增加了。好的设计应该是模块之间只通过模块提供的服务接口来访问,而不是随便调用其他模块的bo。其实webx本身就可以做这个事情,稍加改造及科研实现模块间真正隔离,让一个模块调用不到其他模块bo。
二、Webx级联容器
这里引用下webx官方文档里面截图和说明:

Webx Framework将一个WEB应用分解成多个小应用模块:app1、app2,当然名字可以任意取。
每个小应用模块独享一个Spring Sub Context子容器。两个子容器之间的beans无法互相注入。
所有小应用模块共享一个Spring Root Context根容器。根容器中的bean可被注入到子容器的bean中;反之不可以。将一个大的应用分解成若干个小应用模块,并使它们的配置文件相对独立,这是一种很不错的开发实践。
之前的webx项目我们都是在webx.xml里面配置:
<!-- 引入业务组建定义的Bean.业务Bean定义在component-beans.xml文件中,放在各自Componet中 -->
<beans:import resource="classpath*:component-beans.xml"/>
这种方式作用是把所有模块组元中提供的bean都注入到了webx顶层容器RootContext,所以每个子模块都可以访问其他模块的注入类,并没有达到模块间隔离。
三、正确使用Webx级联容器实现模块隔离
3.1 bean的正确配置
通过webx 子容器和跟容器关系不难想到,我们可以把每个模块的bean 注入到自己子容器中,而不是注入到根容器中,这样其他模块就访问不到本模块子容器中bean.具体来说就是:

其中在1配置文件里面配置需要注入到本模块IOC容器中的bean(这些bean只有本模块可以用,包括本模块的screen,rpc,bo类才能引用,其他模块引用不到)。然后在2处文件里面引用该文件:

。
介绍到这里我们可以实现每个模块真正隔离,但是每个子模块如何对外提供服务那,目前来看所有模块间都是隔离的,但是肯定有需求模块A需要使用模块B的功能。
3.2 模块间(子容器)服务注册与使用
思路是我们可以做一个服务注册与使用的类,具体可以形如:
public class ServiceUtil {
private static ConcurrentHashMap<String, Object> services = new ConcurrentHashMap<String, Object>();
//服务注册
public static void registerService(String name,Object service){
services.put(name, service);
}
//获取服务
public static Object getService(String name){
return services.get(name);
}
}
然后我们在模块中需要暴露给其他模块的bo中设置如下,进行注册:
public class SpeechTestBoImpl implements SpeechTestBo,InitializingBean {
@Autowired
private SpeechServiceBo speechServiceBo;
@Override
public String testSpeechBo() {
// TODO Auto-generated method stub
return "this is speech service ";
}
/**
* 发布服务
*/
@Override
public void afterPropertiesSet() throws Exception {
ServiceUtil.registerService("speech", this);
}
}
通过上面方式可以把当前类注册到服务管理类里面。然后其他模块就可以通过下面的方进行使用该模块服务:
public class SeaServiceRpc {
@Autowired
private SeaServiceBo seaServiceBo;
/*
* 应用定时根据port判断是否有client链接进来
*/
@ResourceMapping("getPortsStatus")
public ActionResult getPortsStatus(@RequestParam(name = "appKey") String appKey,
@RequestParam(name = "md5Sign") String md5Sign, ErrorContext context) {
ActionResult result = new ActionResult();
//这里使用speech模块的服务
SpeechTestBo speechServiceBoTest = (SpeechTestBo) ServiceUtil.getService("speech");
result.setRetValue(speechServiceBoTest.testSpeechBo() + seaServiceBo.startService(0));
return result;
}
}
三、总结
本文为项目中模块化隔离提供了一种思路,目前仅是概念上的思路,还没有真正在项目中使用,希望能给对有这种诉求的童鞋提供参考思路。
欢迎关注微信公众号:技术原始积累 获取更多技术干货

网友评论