|
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2006-07-13
想设计个比较大的项目(MIS类型的,可以认为是个财务,人力资源,供应链,CRM的杂交体),里面有若干模块,将来还会有更多的模块。
现在在架构上有如下需求: 1。有一个核心模块,作为各个模块的基础,负责调用各个具体模块,负责处理诸如事务,权限等问题。 2。各个模块要保持独立性,也就是说,各模块在除核心模块以外不必考虑其他模块是否存在就可以编译,测试。(但不一定能够实际运行,因为有些模块在业务上是耦合紧密的,比如绝大部分模块在业务上都依赖基本档案模块,但在程序上不应该依赖)。 独立性还包括这样的需求。各个模块引用的第三方项目互不干扰。比如A模块引用了Spring2.0,B模块引用了Spring1.1,它们都能正常运行。甚至两个模块可以有两个完全相同的类的定义。 3。但各个模块又有相关性,比如采购模块需要财务模块为其提供接口来根据发票生成凭证,生产制造模块需要采购模块给其提供接口生成采购订单。 4。实现以上需求的基础上,还要保持开发的便利性。 熟悉classloader的结构,粗看一下觉得设计出符合上面需求的架构不算难。 无非就是设计出一个ClassLoader的树形结构: [code:1] java system classloader | | | 核心模块classloader | | | 具体各个模块有自己的一个classloader.[/code:1] 各个模块的classloader都以核心模块为parent classloader,他们都拥有自己模块的类路径。 大家想被别的模块访问的东西都打成jar直接扔到核心模块的类路径里去。 出现问题了如下: 1。核心模块本身的功能实现就需要用到很多第三方的包:hibernate,acegi,spring等等。 也就是说,核心模块本身已经污染了其他的各个具体模块,而除了hibernate以外,其他模块实际上不需要核心模块“附送”的其他第三方库。 2。各模块的公共接口怎么暴露? 假如A模块有个HelloService类希望暴露给其它模块。 [code:1] import someOtherClass public HelloService extend AbstractXXXXService { public HelloObj sayHello(HelloParam1 p1,HelloParam2 p2) { //do anything return new HelloObj(); } }[/code:1] 那需要把什么给放到核心模块里才能被其它模块正常访问呢? 包括: someOtherClass AbstractXXXXService HelloObj HelloParam1 HelloParam2 以及他们本身再引用的类。 倒~,这样岂不是把A模块全部扔到核心模块里了? 好,那修改一下,针对接口编程。 把它们全部抽象成接口: [code:1] interface IHelloSerivce { public IHelloObj sayHello(IHelloParam1 p1,IHelloParam2 p2); }[/code:1] 然后再把IHelloSerivce,IHelloObj,IHelloParam1,IHelloParam2扔到核心模块里。 这样的话,凭空多出许多的不需要的接口。(我觉得,只有IHelloSerivce是必要的。比如P1 p2只是一个简单的struct) 还要有一个地方来注册这个IHelloSerivce是由具体的哪个模块的哪个类来实现的。 对外接口多了也很头痛。 编程的便利性就失去了。 怎么解决这些烦恼? 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
设计起点错误.
这样的系统应该是多系统的集成.各个系统通过Web Service(或者其他机制)松散耦合.这样就不存在需要你所谓classload机制的地方. 我想你所说的接口污染问题是无法避免的,结果就是使程序无法编译,或是Down掉. |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
楼上的想说soa?
呵呵。看来你不理解我想要的。 那在一个服务器上的不同模块互相调用也通过ws? 你试没试过直接方法调用和ws调用之间的性能差距? 把一个pojo暴漏成ws有多少工作量? 就是用spring也要每个ws写一个xml吧? 跨模块调用,事务怎么保证? ws本身是,1。分布式应用,2。不同语言调用的。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
搂主的想法感觉跟eclipse的plug-in及至有些类似,不晓得你参考过eclipse osgi没有。
|
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
引用 呵呵。看来你不理解我想要的。
我不知道我是否了解.但我认为你所说的"较大的项目"如果需要将那末多模块的业务逻辑混合在一个核心模块中,总是有问题的. 如果我没有理解错误,你是试图将一堆异构系统容纳在同一个框架下,同一个进程中运行.但这总是要付出代价的. 松散耦合是一种风险较低的方案.否则不论你的设计有多么完善,你的问题首先是:你怎么知道这些系统都支持你的设计呢? 引用 那在一个服务器上的不同模块互相调用也通过ws?
是的,没什么不可以. 引用 你试没试过直接方法调用和ws调用之间的性能差距?
我了解这个问题.问题是如果你的系统需要太多这样的东西,是不是说明设计出了问题呢?我的理解是可能是你的期望出了问题. 引用 跨模块调用,事务怎么保证?
这不是关键问题.问题还是你的设计怎么降低这种调用的次数. |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
这个问题提得很有深度,也很实际,似乎也只有Classloader方案比较好解决了,不过多个应用互相调用的事务一致性有点麻烦:如果某操作中A应用调用B应用的功能,之间A,B应用任意一个数据库操作失败,那么整个事务就算是失败的.而Spring在这个情形下要解决,只能是同时修改多个版本的代码才能使用同一个TransactionContext, 但是这样一来就违背了当初不互相影响的要求了.或者可以不修改代码,每个子ClassLoader首选其它子ClassLoader的类,但是这样一来所有不同版本的Spring就必须保证完全兼容的了,这个似乎不太可能..
引用 独立性还包括这样的需求。各个模块引用的第三方项目互不干扰。
除了这点,其它都好解决. |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-14
经过试验,想明白一些概念模糊的地方,基本能解决这些问题。
等我设计好了把文档与大家共享。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-18
我觉得core classloader和这些extension module之间不应该是父子关系。
所有的classloader, 包括core和extension module的class loader可以都是系统classloader的儿子。 可以做一个ClassLoaderManager,它负责管理core以及所有module的依赖关系。也就是说,ClassLoaderManager里面包含core和extension。(可以用弱引用,保证垃圾回收) 每个classloader都包含一个对ClassLoaderManager的引用(叫它global)。 查找类的时候,缺省从this找(这步就包括了标准的java classloader的代理模型),如果找不到,那么就交给global去找。 global负责先从core里面找,如果没有,找所有不是当前module的其它module。(如果当前是core,就直接返回,保证core的独立性) 大概应该就可以了。这个模型不同于标准的父子代理关系,它更象一个姐妹代理关系。 |
|
| 返回顶楼 | |
|
最后更新时间:2006-07-18
agree!
我后来想好的模型就是ajoo所描述的。 :) 正在实现ing |
|
| 返回顶楼 | |
|
最后更新时间:2006-08-03
不知做的怎么样了?
我倒是刚写了一个。 发现很难对任意的ClassLoader对象作这种横向组合——sun的class loader的结构不好,对组合不友好。(一个classloader load出来的class,它再load别的class的时候,必然只能从那个classloader走,这样那个组合了所有姐妹classloader的超级classloader就用不到了。) 不过,我写了一个可以对一个目录树里面的所有jar文件进行树形管理的ClassLoader。 同一个目录里面的jar文件会优先于其它目录里面的jar文件。这样,可以按照模块分目录,把jar文件组织起来应该就可以了。这个实现还支持hot-swap。 如果需要,我可以贴出来。 |
|
| 返回顶楼 | |










