灵活的类加载器OSGI

2023-02-28 14:00:36 浏览数 (1)

简介

OSGi中的每个模块(称为Bundle)与普通的Java类库区别并不太大,两者一般都以JAR格式进行 封装[2],并且内部存储的都是Java的Package和Class。但是一个Bundle可以声明它所依赖的Package(通 过Import-Package描述),也可以声明它允许导出发布的Package(通过Export-Package描述)。在OSGi 里面,Bundle之间的依赖关系从传统的上层模块依赖底层模块转变为平级模块之间的依赖,而且类库的可见性能得到非常精确的控制,一个模块里只有被Export过的Package才可能被外界访问,其他的 Package和Class将会被隐藏起来。以上这些静态的模块化特性原本也是OSGi的核心需求之一,不过它和后来出现的Java的模块化系统互相重叠了,所以OSGi现在着重向动态模块化系统的方向发展。

说人话就是OSGI框架,可以对需要加载的类进行精细化的控制,形成一个网状结构,而不是之前的树形的结构。

在今天,通常引入OSGi的主要理由 是基于OSGi架构的程序很可能(只是很可能,并不是一定会,需要考虑热插拔后的内存管理、上下文状态维护问题等复杂因素)会实现模块级的热插拔功能,当程序升级更新或调试除错时,可以只停用、重新安装然后启用程序的其中一部分,这对大型软件、企业级程序开发来说是一个非常有诱惑力的特性,譬如Eclipse中安装、卸载、更新插件而不需要重启动,就使用到了这种特性。

OSGi之所以能有上述诱人的特点,必须要归功于它灵活的类加载器架构。OSGi的Bundle类加载器 之间只有规则,没有固定的委派关系。例如,某个Bundle声明了一个它依赖的Package,如果有其他 Bundle声明了发布这个Package后,那么所有对这个Package的类加载动作都会委派给发布它的Bundle类 加载器去完成。不涉及某个具体的Package时,各个Bundle加载器都是平级的关系,只有具体使用到某 个Package和Class的时候,才会根据Package导入导出定义来构造Bundle间的委派和依赖。另外,一个Bundle类加载器为其他Bundle提供服务时,会根据Export-Package列表严格控制访问范 围。如果一个类存在于Bundle的类库中但是没有被Export,那么这个Bundle的类加载器能找到这个类, 但不会提供给其他Bundle使用,而且OSGi框架也不会把其他Bundle的类加载请求分配给这个Bundle来 处理。

加载方式从简单的树形变成平面网状

经典类加载结构

OGSI网状导入

在OSGi中,加载器之间的关系不再是双亲委派模型的树形结构,而是已经进一步发展成一种更为复杂的、运行时才能确定的网状结构。这种网状的类加载器架构在带来更优秀的灵活性的同时,也可能会产生许多新的隐患。

类加载时可能进 行的查找规则如下:·以java.*开头的类,委派给父类加载器加载。

否则,委派列表名单内的类,委派给父类加载器加载。

否则,Import列表中的类,委派给Export这个类的Bundle的类加载器加载。

否则,查找当前Bundle的Classpath,使用自己的类加载器加载。

否则,查找是否在自己的Fragment Bundle中,如果是则委派给Fragment Bundle的类加载器加载。

否则,查找Dynamic Import列表的Bundle,委派给对应Bundle的类加载器加载。

否则,类查找失败。

实现

NBF(New-Retail Business Framework)是阿里巴巴供应链中台的基础技术团队打造的一个技术PaaS平台,—— 新零售服务开放框架NBF提供标准化业务定义 、 快捷服务开发和生态开放的能力,旨在为生态伙伴提供一整套完整的新零售PaaS和SaaS的解决方案。

所谓标准化业务定义,就是比如一个商家从交易到客户签收都会经历,付款,创单,配送,签收等流程。

所谓快捷开发就是只要接入默认实现,就已经拥有了标准流程。

所谓生态开放能力就是,在以上流程中行业对于配送的要求可能不一样,比如大家电需要预约配送时间,低货值的订单可以驿站代签等,只需要在标准定义中扩展即可。

其中就有用到诸如热插拔,中台部门应用与多行业业务bundle独立部署,bundle有问题快速回滚等问题。

当然bundle与中台也会有RPC协议通讯。

因为现在市面上介绍相关技术的资料比较少,基本都是一些大厂自研还没有开源的业界知名的案例,这里就不过多讨论细节了,不过身为工程师我们可以发散思维,如果自己做一套OSGI框架,需要考虑哪些问题,针对自己做的业务,可以做哪些定制化设计。可以一起讨论。

0 人点赞