在OSGI中,我们可以在运行时更新,激活,停用软件包。
但是我不明白它是如何可能的,因为其他一些人可能会使用这个包的功能。为什么不发生这种情况会使应用程序崩溃?
通常,在JVM中,无论何时运行任何应用程序,它都会加载源类文件和所需的Java API类文件并生成结果。
你能解释一下OSGI的基本架构是什么,以便它允许上述事件发生。
答案 0 :(得分:5)
要理解这一点,您需要查看OSGi格局的两个部分: services 和(Java) classes / interfaces 。
与 services 相关,激活,停用和更新由客户端(用户)和服务提供商之间的合同处理。客户端必须跟踪对可用服务的更改,并在收到服务即将被删除的通知后立即释放服务的使用。此外,它可以跟踪其他服务的可用性,以便在有更好的服务可用时立即更新其参考。请注意,OSGi环境是合作的:非一个强制使用bundle实际释放对服务的引用。因此,不正确的行为可能会导致意外结果。
因此:对于服务,服务的用户负责处理服务可用性的动态。
与Java类/接口相关,意味着类加载,处理由框架本身完成。如果未安装向其他bundle提供类的bundle(通过其Export-Package清单条目宣布),则捆绑包提供的类仍可供已使用它们的bundle使用。只有隐式告诉框架更新bundle之间的类连接(通过org.osgi.service.packageadmin.PackageAdmin
服务上的“刷新”操作,通常通过某种框架控制台提供),对bundle导入的类进行更改。在这种情况下,框架可以停用使用捆绑包,重新连接到不同捆绑包提供的其他类并再次激活。
因此:对于类加载,除非明确告知,否则框架不会更改初始布线。因为捆绑包必须意识到可以随时启动,加载,停止和卸载它们以处理不断变化的上下文。
也许某些情况会使这一点更清晰:
假设bundle LogInterface 中有一个接口定义Log
。此接口提供了一种方法:logMessage(String message)
。在此定义旁边,有一个包 LogProvider ,它提供了一个接口实现,以及一个利用接口 LogUser 功能的包。这三个软件包在OSGi框架中作为软件包和软件包版本1.0.0
安装和启动。 Bundle LogProvider 在服务注册表中注册日志服务对象,并捆绑 LogUser 检索该服务对象并对其进行调用以进行日志记录。
场景1 :假设在不更改接口定义的情况下更新 LogProvider 软件包,例如不仅要记录到控制台,还要记录到文件。在这种情况下,必须停止旧的 LogProvider 包(版本1.0.0),并且必须在框架中安装新的 LogProvider 包(1.1.0)并启动。一旦旧的 LogProvider 捆绑包停止,日志服务就会消失, LogUser 会收到通知(并且必须释放服务对象)。启动新的 LogProvider 软件包后,LogUser软件包可以查找并使用 LogProvider 软件包1.1.0提供的新实现。
场景2 :假设在接口定义中添加了一个允许传递严重性代码的新方法。这意味着logMessage(String message)
方法旁边的Log
接口会获得一个新方法logMessage(int severity, String message)
。由于接口更改,因此卸载了bundle LogInterface 版本1.0.0,并且已安装并启动了bundle LogInterface 版本1.1.0。当然, LogProvider 包也必须更改以提供新方法的实现,因此安装并启动 LogProvider 版本1.3.0。
在这种情况下,卸载LogProvider 1.2.0并启动LogProvider版本1.3.0不会导致LogUser能够检索新提供的服务。这是因为LogProvider 1.3.0从 LogInterface 捆绑包1.1.0和 LogInterface 捆绑包1.0.0中加载了 LogInterface 捆绑包1.1.0和 LogUser 的Log接口定义。要将 LogUser 更新为新接口版本,必须对 LogUser 捆绑包执行捆绑软件刷新。实际上,执行此“刷新”意味着将停止LogUser捆绑包,重新连接到新的LogInterface 1.1.0版捆绑包并重新启动。