osgi导出包和非导出包_了解如何解决OSGI捆绑包

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导出包和非导出包

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值