osgi导出包和非导出包

我想回顾一下OSGI包如何解决并使用Apache Karaf进行演示。 Karaf是基于Apache Felix内核的功能齐全的OSGI容器,并且是Apache ServiceMix集成容器的基石。 对于第一部分,我将讨论OSGI框架如何解决捆绑包。 在第二部分中,我将使用Apache Karaf演示每个规则。 让我们开始吧。

捆绑包解决规则

OSGI 捆绑软件的生命周期定义了捆绑软件的可能状态和过渡。 我们将讨论捆绑包的“已解决”状态,这意味着捆绑包在“安装”之后以及满足其所有必需的依赖关系时可以达到的状态。 传统的Java类加载易受运行时ClassCastException的影响,在这种情况下,来自两个不同类加载器的两个具有相同完全限定名称的类会混合在一起,并且一个错误的类路径空间中将使用一个类。 OSGI的主要目标之一是通过在部署时解决所有依赖关系来避免这种运行时异常,因为在部署时“快速”失败的想法比尝试在运行时跟踪类加载问题更容易调试。 例如,考虑一下如何在Weblogic部署中调试一些未找到的类或类强制转换异常。 OSGI解决了这个问题。 为了使分发包达到“已解决”状态,必须满足其依赖关系。 考虑这样的“快速失败”捆绑解决方案:如果您使用spring应用程序,并且由于缺少bean定义而无法正确连接其中一个bean,那么您将在部署时(而不是在有客户时)知道这一点。调用您的代码。 OSGI遵循相同的原则。 而不是对象级的接线依赖关系,我们是接线模块和类加载的依赖关系。
一个简单的解释,即解决了其依赖关系的捆绑软件可能是这样的:如果捆绑软件导入(导入包装)特定的软件包,则该软件包必须由另一个捆绑软件的导出(导出软件包)提供。 如果捆绑软件A具有Import-Package:org.apache.foo,则必须部署的捆绑软件具有Export-Package:org.apache.foo

对于每个Import-Package包声明,必须有一个具有相同包的对应Export-Package

捆绑包还可以将其他属性附加到它导入或导出的包中。 如果我们在示例中添加了version属性,该怎么办:

Bundle-Name: Bundle A
Import-Package: org.apache.foo;version="1.2.0"

这意味着,捆绑软件A依赖于最低版本为1.2.0的软件包org.apache.foo 。 是的,您没有看错。 尽管使用OSGI可以指定一个版本范围,但是如果您不指定范围而是使用固定版本,则将导致固定值的“最小值”。 如果同一软件包有更高版本,则将使用更高版本 。 因此,除非有相应的包B导出所需的包,否则包A将无法正确解析:

Bundle-Name: Bundle B
Export-Package: org.apache.foo;version="1.2.0"

请注意,反之则不然......如果捆B出口版本1.2.0,则不需要捆绑到指定版本1.2.0。 它可以使用此导入并解决问题:

Bundle-Name: Bundle A
Import-Package: org.apache.foo

这是因为导入会声明所需的版本。 导出的版本未指定导入包必须使用的任何内容(它适用于所有属性,而不仅仅是版本)。

Import-Package准确规定了它需要的版本(或属性),并且必须存在具有相同属性的相应Export-Package

如果您遇到方案A导入软件包并指定由两个软件包提供的版本的情况,会发生什么情况:

Bundle-Name: Bundle A
Import-Package: org.apache.foo;version="1.2.0"

Bundle-Name: Bundle B
Export-Package: org.apache.foo;version="1.2.0"

Bundle-Name: Bundle C
Export-Package: org.apache.foo;version="1.2.0"

捆绑软件A使用哪个捆绑软件?
答案是,这取决于首先安装了哪个捆绑包(B或C)。

当找到多个具有相同版本的软件包时,首先安装的软件包用于满足依赖性

在解决一些捆绑包之后,热部署捆绑包会使事情变得更加复杂。 如果先安装Bundle B,然后尝试同时安装Bundle A和以下Bundle D,该怎么办:

Bundle-Name: Bundle D
Export-Package: org.apache.foo;version="1.3.0"

从上面我们可以看到,捆绑软件A(1.2.0)中的版本声明表示最低版本为1.2.0; 因此,如果有更高版本可用,它将选择该版本(本例中为Bundle D版本1.3.0)。 但是,这将我们带到了束分解的另一个时间规则:

已解决的捆绑包比未解决的捆绑包具有更高的优先级

原因是OSGI框架倾向于支持给定捆绑软件的可重用性。 如果已解决,并且新的捆绑软件需要它,那么即使不需要,它也不会尝试拥有同一软件包的许多其他版本。

捆绑“使用”指令

上面关于束解析的规则仍然不够,并且在运行时仍可能使用错误的类,从而导致类转换异常或类似事件。 你看到什么可能会丢失吗?
如果我们有这种情况怎么办。 捆绑软件A导出一个包org.apache.foo ,其中包含一个类FooClass。 FooClass具有一个返回BarClass类型的对象的方法,但是BarClass不在捆绑软件的类空间中定义,它的导入方式如下:
public class FooClass {public BarClass execute(){ ... }
}

Bundle-Name: Bundle A
Import-Package: org.apache.bar;version="3.6.0"
Export-Package: org.apache.foo;version="1.2.0"

到目前为止,只要有另一个捆绑包可以正确导出具有正确版本的org.apache.bar ,一切就可以了。

Bundle-Name: Bundle B
Export-Package: org.apache.bar;version="3.6.0"

这两个捆绑包可以解决。 现在,如果我们再安装两个捆绑包,捆绑包C和捆绑包D如下所示:

Bundle-Name: Bundle C
Import-Package: org.apache.foo;version="1.2.0", org.apache.bar;version="4.0.0"

Bundle-Name: Bundle D
Export-Package: org.apache.bar;version="4.0.0"

我们可以看到Bundle C从Bundle A导入了一个包org.apache.foo。Bundle C可以尝试使用org.apache.foo中的FooClass,但是当它获得返回值(一种BarClass类型)时,会发生什么? 捆绑软件A希望使用BarClass的3.6.0版本,但是捆绑软件C则使用的是4.0.0版本。 因此,在运行时捆绑包内使用的类不一致(即,您可能会遇到某种类型的不匹配或类强制转换异常),但按照上述规则,所有内容在部署时仍可以很好地解决。 我们需要告诉任何导入org.apache.foo的人 ,我们使用的是来自org.apache.bar特定版本的类,如果要使用org.apache.foo ,则必须使用与导入的版本相同的类。 这正是uses指令的作用。 让我们更改包A以确切指定:

Bundle-Name: Bundle A
Import-Package: org.apache.bar;version="3.6.0"
Export-Package: org.apache.foo;version="1.2.0"";uses:=org.apache.bar

给定捆绑软件A的新配置,捆绑软件将无法从上方正确解析。 捆绑软件C无法解析,因为它导入了org.apache.foo,但是捆绑软件A上的“使用”约束指定C必须使用与org.apache.bar相同的版本(3.6.0),否则捆绑软件将尝试部署时无法解决。 解决方案是将Bundle C中org.apache.bar的版本更改为3.6.0。

使用Apache Karaf

OSGI容器Karaf基于Apache Felix核心,但是如果需要可以替换Equinox核心。 Karaf是功能齐全的OSGI容器,并且是Apache ServiceMix集成容器的基石。 ServiceMix基本上是Karaf,但专门针对Apache Camel,Apache ActiveMQ和Apache CXF进行了调整。
本教程将需要Maven和Karaf。 从maven网站下载maven 。 按照Karaf网站上的入门指南中的说明下载并安装karaf。 您还将需要此示例附带的代码。 您可以在我的github仓库中获得它 。 获得它之后,请确保从顶级项目运行“ mvn install”。 这将构建并将所有捆绑软件安装到本地 Maven存储库中。 尽管可以通过几种不同的方式安装捆绑软件,但使用maven最为简单。 请注意,此示例代码主要由没有任何实际Java类的程序包名称组成(本教程指定的情况除外)。

首先要做的是启动karaf。 在普通发行版中,不应安装捆绑软件。 通过在karaf命令行中执行“ osgi:list”来验证这一点。 按照顺序,我们将测试上面给出的规则。

对于每个Import-Package包声明,必须有一个具有相同包的对应Export-Package

为了测试此规则,让我们从示例捆绑软件中安装捆绑软件A。 捆绑包A指定“ org.apache.foo”包的导入包。 根据第一个规则,此捆绑包无法移至“已解决”状态,因为没有对应的捆绑包具有org.apache.foo的“导出包”。
在karaf命令行中,输入“ osgi:install mvn:explore-bundle-resolution / bundleA / 1.0?”。 这将安装bundleA捆绑软件。 现在再次执行“ osgi:list”。 您应该看到捆绑软件已安装,并且在“状态”列下应显示为“已安装”。 现在,尝试“ osgi:resolve bundle id ”,其中bundle id是“ osgi:list”命令中列出的ID。 这将尝试解决所有捆绑软件依赖关系,并将其置于“已解决”状态。 但是,它无法解决。 再次键入“ osgi:list”以查看捆绑软件的状态。 即使我们要求OSGI解决它,它仍然处于“已安装”状态。 让我们找出原因。 执行“ osgi:headers 捆绑包ID ”。 在导入包下,您应该看到以红色列出的包名称org.apache.foo。 缺少此依赖项,因此让我们添加它。 输入“ osgi:install -s mvn:explore-bundle-resolution / bundleB / 1.0?”。 注意命令中的“ -s”开关。 这告诉OSGI一旦安装了捆绑软件就启动它。 现在,再次键入osgi:resolve命令(带有适当的捆绑软件ID)。 现在,这将解决捆绑包。

Import-Package准确规定了它需要的版本(或属性),并且必须存在具有相同属性的相应Export-Package

让我们安装捆绑软件C:“ osgi:install -s mvn:explore-bundle-resolution / bundleC / 1.0? 再次列出捆绑软件,您将看到尽管捆绑软件C依赖于org.apache.foo,但它指定的Import-Package的特定版本为1.5。 没有解决的版本1.5,因此捆绑软件C也将无法解决。 捆绑包D恰巧导出了版本等于1.5的软件包org.apache.foo。 使用-s启动捆绑软件D,就像安装其他捆绑软件一样安装它。 现在尝试解析捆绑软件C,它应该可以工作(“ osgi:resolve bundle id ”)。

当找到多个具有相同版本的软件包时,首先安装的软件包用于满足依赖性

该规则表示,如果有多个使用相同版本导出的软件包,则OSGI将在尝试解析导入软件包的软件包时选择要使用的第一个安装的软件包。 继续前面的示例,其中我们安装了捆绑软件C和D…请考虑捆绑软件D导出org.apache.foo; version = 1.5。 因此,如果我们安装输出完全相同的软件包和版本的软件包F,则应该看到软件包C是用软件包D中的软件包而不是软件包F来解决的。让我们看看..安装软件包F:“ osgi:install -s mvn: Explore-bundle-resolution / bundleF / 1.0?。 执行osgi:list并查看捆绑软件D和F均已正确安装并且为“活动”状态。 这是OSGI的一项很酷的功能:我们可以同时部署同一软件包的多个版本(在此示例中包括完全相同的版本)。 现在,我们应该卸载捆绑软件C并重新安装它,以查看它使用哪个捆绑软件来解析其org.apache.foo的导入。 尝试运行“ osgi:uninstall bundle id ”以卸载捆绑软件C。现在,使用上面的命令重新安装它。 它应该确定使用捆绑软件D。使用“ package:import 捆绑软件ID ”进行验证。 您可以尝试左右切换,以解决F问题。 您可能需要使用“ osgi:refresh”来刷新OSGI捆绑软件。

已解决的捆绑包比未解决的捆绑包具有更高的优先级

在某种程度上,我们已经在上一条规则中看到了这一点,但是该规则在热部署时会起作用。 这留给读者练习,因为这篇文章已经很长了,我接下来将介绍“ uses”指令。

捆绑“使用”指令

“ uses”指令添加了最后的规则和约束之一,以避免运行时类广播异常。 为了模拟“ uses”指令的工作方式,我们将安装捆绑软件G,H,I和J,并注意容器如何执行“ uses”指令。
捆绑软件G代表一种“服务”模块,客户端模块可以调用该服务模块以“执行”某种形式的处理并返回结果。 它返回的结果是来自捆绑软件H的BarClass类型的对象。但是,如果客户端调用捆绑软件G,它也必须使用捆绑软件H的BarClass,否则将导致类强制转换异常。 在我们的示例中,捆绑软件I是客户端代码,捆绑软件J代表BarClass的不同版本。 以您喜欢的任何顺序安装捆绑软件,但我的演示遵循以下顺序:J,H,G,I。请注意,即使捆绑软件H是org.apache.bar的版本确实是来自捆绑软件H的2.0.0版本。是第二次安装的(与上面的规则相反)。 这是因为捆绑软件G指定了“ uses”指令依赖于org.apache.bar的特定版本。

参考:在Christian Posta Software博客上,从我们的JCG合作伙伴 Christian Posta 了解如何解决OSGI捆绑 软件 。

翻译自: https://www.javacodegeeks.com/2012/05/understanding-how-osgi-bundles-get.html

osgi导出包和非导出包

osgi导出包和非导出包_了解如何解决OSGI捆绑包相关推荐

  1. 常用jar包_几个解决 Maven Jar 包冲突的小技巧.

    前言 大家在项目中肯定有碰到过Maven的Jar包冲突问题,经常出现的场景为: 本地运行报NoSuchMethodError,ClassNotFoundException.明明在依赖里有这个Jar包啊 ...

  2. unity创建项目不添加包_使用精选的资产捆绑包和Unity Learn Premium可以更高效地创建项目

    unity创建项目不添加包 For a limited time, we're bundling and discounting some of our most popular assets and ...

  3. Java导出Excel公式非空判断_使用poi导成excel的一个类型判断函数

    /** * 获取cell中的数据 * @param cell * @return */ private String readCell(HSSFCell cell) { if (null == cel ...

  4. 眼图 非差分线_利用眼图解决USB在布线中的信号完整性问题

    EDA365欢迎您登录! 您需要 登录 才可以下载或查看,没有帐号?注册 x 本帖最后由 lifree 于 2020-2-5 14:37 编辑 2 ]3 p' D% B4 \  {/ n # V&am ...

  5. 了解如何解决OSGI捆绑包

    我想回顾一下OSGI包如何解决并使用Apache Karaf进行演示. Karaf是基于Apache Felix内核的功能齐全的OSGI容器,并且是Apache ServiceMix集成容器的基石. ...

  6. Facebook Instant Game 捆绑包配置方法

    捆绑包配置 小游戏的一些配置可以通过开发者门户或游戏捆绑包中嵌入的专用 JSON 文件来实现.在开发者门户中更新某个值时,将全局更改所有游戏版本中的这个值,而捆绑包配置只会更改某个特定捆绑包中的这个值 ...

  7. Netty解决TCP粘包/拆包导致的半包读写问题

    一.TCP粘包/拆包问题说明 TCP是个"流"协议,就是没有界限的一串数据.TCP底层并不了解上层业务数据的具体含义,它会根据TCP缓冲区的实际情况进行包拆分,所以在业务上认为,一 ...

  8. R语言数据导出(数据保存、导出、持久化到本地指定目录文件)、使用foreign包的write.dta函数将dataframe导出为Stata格式dta文件

    R语言数据导出(数据保存.导出.持久化到本地指定目录文件).使用foreign包的write.dta函数将dataframe导出为Stata格式dta文件 目录

  9. 【Unity入门】资源包导入和导出

     [Unity入门]资源包导入和导出     大家好,我是Lampard~~     欢迎来到Unity入门系列博客,所学知识来自B站阿发老师~感谢 (1)资源目录     Unity的资源(模型,场 ...

最新文章

  1. K-means聚类自定义距离计算
  2. Ouroboros:一个可证明安全的PoS区块链协议 (共识介绍)
  3. 深度学习和目标检测系列教程 8-300:目标检测常见的标注工具LabelImg和将xml文件提取图像信息
  4. oracle定时器在项目中的应用
  5. 三级嵌入式 汇编指令汇总
  6. 前端学习(3148):react-hello-react之getSnapBeforeUpdate
  7. Hadoop—如何查看HDFS默认的ns命名空间和所有命名空间列表
  8. bzoj1596[Usaco2008 Jan]电话网络*
  9. 基于verliog的异步模10计数器(含模块代码以及测试代码)
  10. GalForUnity简介
  11. 微信刷票python代码_微信刷票漏洞详解, Python脚本实现一秒破万!
  12. 【Android】自定义View、画布Canvas与画笔Paint
  13. 2021年「博客之星」参赛博主:尔嵘
  14. 这十个嵌入式工程师最青睐的树莓派扩展板让你受用半生
  15. Phonetic symbol 清辅音 - θ 与 s
  16. iPhone 12 pro max卡槽怎么插双卡
  17. 香农编码C程序及演示结果
  18. 如何在Tableau Desktop中创建自定义调色板 - 优阅达
  19. 月入过万——网店推广实战方法(第2版)
  20. 基于STM32F103C8T6的HC-06蓝牙通信

热门文章

  1. 关于Java序列化你应该知道的一切
  2. 【最全最详细】publiccms实现将公共部分提取成单独模块引入
  3. 子列表只是原列表的一个视图
  4. 压力与动力是否成正比?
  5. Gradle 简单使用
  6. MySQL8.0: Serialized Dictionary Information(SDI) 浅析
  7. java登录界面命令_Java命令行界面(第25部分):JCommando
  8. 因此,Oracle杀死了java.net
  9. java ab工具_(ab)使用Java 8 FunctionalInterfaces作为本地方法
  10. owin 怎么部署在云中_使用Boxfuse轻松在云中运行Spring Boot应用程序