如果你的场景不是对动态化(并且是无状态的那种动态化)有强烈的需求,那不要选OSGi。
仅仅是为了模块化,隔离这些,还不如自己做一个简单的实现,并且可以遵守现在的开发习惯,不要去挑战众多人的开发习惯和通用的知识体系,那对系统维护来说绝对会是一个灾难,只能说或许等到将来Java从语言级支持了可能才OK。
OSGi并没有提供对象状态保留的处理,这也就意味着,基本上在一次更新后,此次更新的Bundle以及相关的bundle因为classloader的重建,其对象的状态数据都丢失了
java应用架构设计模块化模式与OSGI读书笔记
因此直接从第8章看起: 1. 模块化的设计模式5种模式分别为: 1) 基本模式 主要定义了其它模式的赖以存在的基础元素。基本模式关注将模块作为可重用单元,依赖管理以及内聚,设计出良好的软件系统要遵循基本模式。包含: 管理关系:设计模块关系。 模块重用:强调模块级别的重用。 模块内聚:模块的行为应该只服务于一个目的。 2) 依赖模式 非循环关系:模块关系必须是非循环的。 等级化模块:模块关系应该是等级化的。 物理分层:模块关系不应该违反概念上的分层。 容器独立:模块应该独立于运行时容器。 独立部署:模块应该是独立的可部署单元。 3) 可用性模式 发布接口:使模块的发布接口众所周知。 外部配置:模块应该可以在外部进行配置。 默认门面:为具有底层实现的细粒度模块创建一个门面,使其成为细粒度模块的一个粗粒度入口。 4) 扩展性模式 抽象化模块:依赖模块的抽象元素。 实现工厂:使用工厂创建模块的实现。 分离抽象:将抽象与实现他们的类放在各自独立的模块中。 5) 通用模式 就近异常:异常应该接近抛出他们的类或接口。 等级化构建:按照模块的等级执行构建。 测试模块:每个模块应该有一个应对的测试模块。 ---------------------------------------------
基本模式: 管理关系:设计模块关系 模块和模块之间的关系: 如果修改模块M2的内容,会影响另一个模块M1,那么就可以说M1物理依赖于M2. 关系分为两种: 输入依赖,输出依赖或者二者兼备。 如果有其他模块依赖当前模块中的类,那么就说存在输入依赖。 如果模块依赖其他模块中一个或多个类,那么就说存在输出依赖。
Client为输出依赖,service为输入依赖
间接依赖图示: 也叫传递性依赖,间接依赖至少要涉及三个模块,service模块即作为输出依赖也作为输入依赖,service模块作为client和subsystem模块之间的桥梁,client模块和subsystem模块就有间接依赖关系。若subsystem模块有什么变化可能会影响service和clientmok。
具备过多的输入和输出依赖模块是最难管理的,因为他们被大量其他模块使用,同时本身也使用了大量的模块。同时具备输入和输出依赖的模块需要最大程度上的灵活性,应该通过依赖模式管理这种灵活性。要不惜一切代价避免循环依赖关系。要灵活运用抽象化模块模式和分离抽象模式来管理模块依赖。 模块之间的紧耦合是不好,可以通过关系进行反转或者完全消除,来把紧耦合的关系拆开。 书中样例:
Customer类实现了DiscountCalculator接口,并且和bill类有依赖关系 Bill类依赖了DiscountCalculator接口。 因此customer.jar模块依赖billing.jar, customer.jar在构建和运行时都需要billing.jar。 要想单独使用customer.jar时而不需要billing.jar那就需要反转关系来实现了。 1. 反转关系 将Bill重构为一个接口。接下来,为了避免分割包,将Bill接口转移到与Customer类相同的模块中。
1. 消除关系 反转关系允许独立于billing.jar模块部署customer.jar模块。在反转关系之前,能够独立的测试部署billing.jar模块。在反转关系之后,我们能够独立测试和部署customer.jar模块。但是,如果想独立测试和部署这两个模块,那该怎么办呢?为了做到这一点,我们需要完全消除他们之间的关系。 只需要把Bill和DiscountCalculator这两个接口打包到独立的模块中。不需要其他的代码变化。
识别模块是设计模块化软件系统的第一步。紧随其后的就是管理这些模块间的关系。模块之间的这些关系称为结合点,系统中的这些地方需要最特别的关注以确保灵活的系统设计。如果没有关注模块间的关系,只是将系统拆分为一系列的模块并不会带来很明显的好处。
|
https://www.jianshu.com/p/2c0c8091e3de
模块化的意义
解决Java模块化的局限:可见性控制不够、Jar包灾难、部署和管理缺少支持。
通过显示定义能力(Export-Package)和依赖(Import-Package),可以优化设计,让系统更加“高内聚低耦合”(软件开发的终极目标)。
促进协同开发,提高开发效率。
模块化有两个方面:运行时模型和开发模型。开发模型包括编程模型和设计范式
所有的方面都是很重要的,但是如果不能理解如何设计模块化的软件将会降低使用模块 化运行时或框架所带来的益处。
本书主要讨论的是如何解决设计范式的问题。
1. 运行时模型
运行时模型关注如何在运行时对模块化的软件系统进行管理
运行时模块化系统支持:封装、动态部署、版本管理、依赖管理;
2. 开发模型
开发模型解决的问题是开发人员怎样使用框架构建软件应用
分:
2.1)编程模型
为了减少对模块系统 API 的依赖,框架和一些技术必须提供一定程度的抽 象,这样代码就不会直接依赖框架的 API 了。这些框架和技术的示例包括 OSGi Blueprint 服务、声明式服务(Declarative Service)、Spring Dynamic Module 以及 iPojo
2.2)设计范式
理解单个模块的重量级和粒度,并使用合适的技术管理模块间的耦合
一个组织如何创建更加模块化的架构?模块的合适粒度是什么样 的?模块间应该存在什么程度的依赖?怎样最小化模块依赖?如何将大的模块拆分为一 些更小的更加内聚的模块?怎样将已有的庞大软件系统模块化?应该在何时这样做?这 些问题和其他问题是重要的架构和设计问题,
-- 面向对象(Object-Oriented,OO)编程:“优先使用 对象组合而不是对象继承”以及“面向接口编程而不是实现”)
-- 以及企业级 JavaBean(Enterprise JavaBean,EJB):企业级 JavaBean,尤其是其中的实体 bean,曾被视为将 Java 开发的业务应用进行组 件化的一种方式。EJB 的运行时能力是很有吸引力的——事务、持久化、安全性、透明 等——并且它们直接合并到了平台中。不过,有两个很明显的问题:开发模型复杂并且 无法很好地理解。
SOLID原则:
单一职责原则告诉我们实现类要职责单一;
里氏替换原则告诉我们不要破坏继承体系;
依赖倒置原则告诉我们要面向接口编程;
接口隔离原则告诉我们在设计接口的时候要精简单一;
开闭原则是总纲,他告诉我们要对扩展开放,对修改关闭。
迪米特法则告诉我们要降低耦合。
异常应该接近抛出它们的类(接口)
如果异常随处放,将会出现不希望的模块间依赖