了解如何解决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依赖于软件包org.apache.foo ,其最低版本为1.2.0。 是的,您没有看错。 尽管使用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"

到目前为止,只要有另一个捆绑包可以正确导出具有正确版本的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"

给定捆绑软件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软件博客上,从我们的JCG合作伙伴 Christian Posta 了解如何解决OSGI捆绑 软件 。


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372429.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件共享服务器imac,iMac怎么在网络上共享设备windows文件夹和服务 | MOS86

本章通过向您展示如何在网络和Mac和Windows计算机之间共享文件,文件夹和设备,帮助您充分利用您的iMac网络连接。→使用Macs共享文件和文件夹使用AirDrop和文件共享→与Windows 7计算机共享文件→设置共享权限→使用共享表快速在线共享文件→共享和访问网…

【转】 简单理解Socket

题外话 前几天和朋友聊天,朋友问我怎么最近不写博客了,一个是因为最近在忙着公司使用的一些控件的开发,浏览器兼容性搞死人;但主要是因为这段时间一直在看html5的东西,看到web socket时觉得很有意思,动手写…

.NET基础

.NET C# ASP.NET关系:.NET是一个平台,提供程序运行的虚拟机环境和类库。 C#是.Net平台上的一种语言,其他语言还有VB.NET PowerShell等。 ASP.NET是在.NET下的网站开发技术。 安装.NET FrameWork就可以运行。VS集成安装了.NET FrameWork. 控制…

业务活动监视器(BAM)2.0带来的革命

生产兼具精益和企业价值的中间件是一项艰巨的工作。 它要么不存在,要么需要创新的思维(很多),并且需要在实现中反复进行。 业务风险很大,但是如果您做对了,它就会使您领先于其他任何公司。 这就是为什么我们…

oracle销售服务器吗,oracle 服务器 版本

oracle 服务器 版本 内容精选换一换Atlas 800 训练服务器(型号 9010)安装上架、服务器基础参数配置、安装操作系统等操作请参见《Atlas 800 训练服务器 用户指南 (型号9010)》。Atlas 800 训练服务器(型号 9010)适配操作系统如表1所示。请参考表2下载驱动和固件包。Atlas 800 训…

Vue组件间通信:一个例子学会Vue组件-Vue.js学习总结)(转载)

详情请点击 http://www.jianshu.com/p/9ad1ba89a04b转载于:https://www.cnblogs.com/zhongjiang/p/6694459.html

必填字段的自定义JSF验证器

实现EditableValueHolder接口的JSF组件具有两个属性“ required”和“ requiredMessage” –一个标志,指示用户需要输入/选择非空值,以及一个用于验证消息的文本。 我们可以使用它,但是它不够灵活,我们不能直接在视图中&#xff0…

java 转码%2f%_JS和JAVA中常用的编码转码函数

js中escape,encodeURI,encodeURIComponent函数和unescape,decodeURI和decodeURIComponent函数的功能1.escape方法对String对象编码,escape方法返回一个包含了"转义序列"的字符串值。除了ASCII字母和数字,以及这几个符号 *-/._外(共有1052769个字符不会被编…

mybatis 下划线转驼峰配置

一直以来&#xff0c;在sqlmap文件中&#xff0c;对于数据库中的下划线字段转驼峰&#xff0c;我们都是通过resultmap来做的&#xff0c;如下&#xff1a; <resultMap id"ISTableStatistics" type"com.medsoft.perfstat.pojo.ISTableStatistics" > &…

Python练习-迭代器-模拟cat|grep文件

代码如下: 1 # 编辑者&#xff1a;闫龙2 def grep(FindWhat):3 fopen("a.txt","r",encoding"utf8")#以只读的方式打开a.txt文件4 while True:5 try:6 fline next(f).strip()#由于File类型本身就是一个迭代器,所以直…

Spring和JSF集成:转换器

使用任何Web框架时&#xff0c;都不可避免地需要将用户输入的数据从String为其他类型。 尽管Spring和JSF在设计和功能上确实有很大的不同&#xff0c;但它们都具有转换器策略来处理此问题。 让我们从春天开始。 Spring 3引入了一个全新的转换框架&#xff0c;该框架允许将任何类…

nacos配置ap_Nacos 1.0.0 功能预览

本文来自于我的个人主页&#xff1a;Nacos 1.0.0 功能预览&#xff0c;转载请保留链接 ;)Nacos 1.0.0 是正式 GA 的版本&#xff0c;在架构、功能和API设计上进行了全方位的重构和升级&#xff0c;1.0.0版本标志着Nacos的架构已经稳定&#xff0c;API列表最终确定。升级到1.0.0…

poj 2229 Sumsets

题目大意&#xff1a; 一个数由2的幂次数的和构成&#xff0c;问有几种构成方式&#xff1f; 主要是找规律 代码如下 1 #include <cstdio>2 #include <cstring>3 int n;4 #define M 10000000005 int dp[1000002];6 7 int main(int argc, char const *argv[])8 {9 …

html 甘特图_Rplotly|交互式甘特图(Gantt chart)项目管理/学习计划

甘特图(Gantt chart)&#xff0c;又常被称为横道图或者条状图&#xff0c;是现代企业项目管理领域运用最为广泛的一种图示。就是通过条形来显示项目的进度、时间安排等相关情况的。项目管理外&#xff0c;也可以用来管理学习计划。绘制甘特图的工具有很多&#xff0c;本文介绍使…

使您的Spring Security @Secured注释更干燥

最近&#xff0c;Grails用户邮件列表中的一个用户想知道在定义Secured批注时如何减少重复 。 在Java批注中指定属性的规则非常严格&#xff0c;因此我看不到直接执行他所要求的方法的方法。 使用Groovy并没有真正的帮助&#xff0c;因为Groovy类中的注释大部分与Java中的注释几…

阅读《大型网站技术架构》 第三章心得

今天阅读了《大型网站技术架构》 的第三章&#xff0c;这一章主要讲解了大型网站核心架构要素&#xff0c;并且概括的讲解了相应的实现方法。 软件架构除了系统功能需求外&#xff0c;还需要关注性能、可用性、伸缩性、扩展性、安全性。 其中性能是网站的重要指标。优化网站性能…

easyui数据表格重置_数据库三种删除方式

第一种 使用delete 语句特点&#xff1a;delete 属于数据库操纵语言DML&#xff0c;表示删除表中的数据&#xff0c;删除过程是每次从表中删除一行&#xff0c;并把该行删除操作作为事务记录在日志中保存可以配合事件&#xff08;transaction&#xff09;和 回滚&#xff08;ro…

main函数之间的代码操作

全局对象的构造函数会在main函数之前执行。转载于:https://www.cnblogs.com/yingl/p/5817123.html

Windows 自启动总结《转》

开机启动项  【启动项目就是开机的时候系统会在前台或者后台运行的程序】  当Windows&#xff08;操作系统&#xff09;完成登录过程&#xff0c;进程表中出现了很多的进程&#xff01;Windows在启动的时候&#xff0c;自动加载了很多程序。  许多程序的自启动&#xff0…

win10多合一原版系统_微软Win10专业版制作多合一系统安装盘教程

微软Win10怎么制作多合一系统安装盘?和Win10家庭版、win10企业版&#xff0c;win10教育版相比&#xff0c;微软Win10专业版是最受大家喜欢的操作系统&#xff0c;那么在安装Win10操作系统的时候&#xff0c;我们就不得不准备多个不同版本的系统安装盘。可是你知道微软Win10专业…