模块隔离
模块隔离
在一个简单的

当这个系统承载的业务变多了之后,系统可能演化成上图中右边的这种方式。在上图的右边的部分中,一个系统承载了两个业务,一个是
当系统越来越大,最后需要做服务化拆分的时候,就需要花费非常大的精力去梳理模块和模块之间的关系。我们来区分几个常见的模块化形式:
- 基于代码组织上的模块化:这是最常见的形式,在开发期,将不同功能的代码放在不同
Java 工程下,在编译期被打进不同jar 包,在运行期,所有Java 类都在一个classpath 下,没做任何隔离; - 基于
Spring 上下文隔离的模块化:借用Spring 上下文来做不同功能模块的隔离,在开发期和编译期,代码和配置也会分在不同Java 工程中,但在运行期,不同模块间的Spring Bean 相互不可见,DI 只在同一个上下文内部发生,但是所有的Java 类还是在同一个ClassLoader 下; - 基于
ClassLoader 隔离的模块化:借用ClassLoader 来做隔离,每个模块都有独立的ClassLoader ,模块与模块之间的classpath 不同,SOFAArk 就是这种模块化的实践方式。
OSGi 模块化
提到模块化,不得不提
OSGi 的类隔离

通过这种方式,可以控制一个模块特定的类才可以被另一个模块所访问,达到了一定程度地模块的隔离。但是,光通过类的导出导入来解决类的引用问题还不够,还需要去解决实例的引用的问题,我们往往希望能够直接使用对方模块提供的某一个类的实例,而不是自己去
OSGi 的声明式服务
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ITodoService">
<implementation class="com.example.e4.rcp.todo.service.internal.MyTodoServiceImpl"/>
<service>
<provide interface="com.example.e4.rcp.todo.model.ITodoService"/>
</service>
</scr:component>
也可以同样的通过
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="XXXService">
<reference name="ITodoService"
interface="com.example.e4.rcp.todo.model.ITodoService"
bind="setITodoService" cardinality="0..1" unbind="unsetITodoService"
policy="dynamic" />
<implementation class="com.example.e4.rcp.todo.service.internal.XXXServiceImpl"/>
</scr:component>
通过声明式服务的方式,我们就可以直接在一个
OSGi 的模块化的问题
但是在实践的过程中,
SOFA 模块化
为了解决传统的模块化方案模块化不彻底的问题,以及


以
- 运行时,每个
SOFABoot 模块的Spring 上下文是隔离的,模块间定义的Bean 不会相互影响; - 每个
SOFABoot 模块是功能完备且自包含的,可以很容易在不同的SOFABoot 应用中进行模块迁移和复用,只需将SOFABoot 模块整个拷贝过去,调整Maven 依赖,即可运行。
当一个模块需要调用另一个模块里面的一个
<sofa:service ref="sampleBean" interface="com.alipay.sofaboot.SampleBean"/>
使用服务的模块可以在其配置文件(也可以通过
<sofa:reference id="sampleBean" interface="com.alipay.sofaboot.SampleBean"/>
通过这种方式,一个模块就可以清晰地知道它提供了哪些服务,引用了哪些服务,和其他的模块之间的关系也就非常清楚了。但是