定义


OSGi(Open Service Gateway Initiative)技术是面向Java的动态模型系统。

这个框架实现了一个优雅、完整和动态地组价模型。应用程序(称为bundle)无序重新引导可以被远程安装、启动、升级和卸载。

OSGi服务平台提供在多种网络设备上无需重启的动态改变构造的功能。

为了最小化耦合度和促使这些耦合度可管理,OSGi技术提供一种面向服务的架构,它能使这些组件动态地发现对方。

OSGi联盟已经开发了例如像HTTP服务器、配置、日志、安全、用户管理、XML等很多公共功能标准组件接口。这些组件的兼容性插件实现可以从进行了不同优化和使用代价的不同计算机服务提供商得到。然而,服务接口能够基于专有权基础上开发。

OSGi的主要职责就是为了让开发者能够创建动态化、模块化的Java系统。

OSGi 框架


OSGi框架从概念上可以分为三层:模块层、生命周期层和服务层。

  • Module Layer:模块层主要涉及包及共享的代码;
  • Lifecycle Layer:生命周期层主要涉及Bundle的运行时生命周期管理;
  • Service Layer:服务层主要涉及模块之间的交互和通信。

模块层


模块层是 OSGi 框架中最基础的部分。

OSGi 的模块化,是通过为 Jar 包添加metadata 来定义哪些类该暴露,哪些类该隐藏,其控制单元叫做 Bundle(jar 包)。

Bundle

首先,必须先了解一个基本概念——什么是Bundle?

什么是 Bundle ?

bundle 是以 jar 包形式存在的一个模块化物理单元,里面包含了代码,资源文件和元数据(metadata),并且jar包的物理边界也同时是运行时逻辑模块的封装边界。

如何定义 Bundle

Bundle 是 OSGi 中的基本组件,其表现形式仍然为 Java 概念中传统的 Jar 包。
通过 META-INF 目录下的 MANIFEST.MF 文件对其予以进一步的定义。

通常一个 MANIFEST.MF 文件的内容如下:

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Util
Bundle-SymbolicName: com.ibm.director.la.util
Bundle-Version: 1.0.0
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Import-Package: org.osgi.framework;version="1.3.0"
Export-Package: com.ibm.director.la.util;uses:="org.osgi.framework"
Bundle-ClassPath: lib/junit.jar,

MANIFEST.MF 文件存储的实际上是 Bundle 的元数据。

元数据的内容可以精确的定义 Bundle 的各种特征,同时能更好的对 Bundle 进行标识同时帮助用户对Bundle进行理解。

生命周期层


生命周期层在OSGi框架中属于模块层上面的一层,它的运作是建立在模块层的功能之上的。
生命周期层的主要功能是控制动态安装、开启、关闭、更新和卸载的bundles。

生命周期层让你能够从外部管理应用或者建立能够自我管理的应用(或者两者的结合),并且给了应用本身很大的动态性。

前面已经了解了 Bundle 的概念和作用。但是要真正使用 Bundle,需要使用生命周期层的API,来和OSGi框架的生命周期层进行交互。

在标准的Java编程中,可以通过将jar包放到classpath中来使用它。而bundle则不是这样,Bundle只有在被安装(install)到一个OSGi框架的运行实例中才能用起来。并且OSGi框架支持对这些bundle完整的生命周期管理,并且支持这些管理操作在应用执行完成。

下图为 Bundle 生命周期的状态转移图:

重要接口

生命周期层的API主要是由以下三个核心接口来组成的:BundleActivator,BundleContext 和 Bundle。

  • BundleActivator:让你能够捕捉bundle的start和stop事件,并对这两个事件作出自定义的反应。
  • BundleContext:一个bundle在框架中的执行时上下文,这个上下文提供了和框架进行交互的方法。
  • Bundle:在逻辑上表示了一个bundle,OSGi环境中的一个物理bundle对应了一个bundle对象。该对象中包含了bundle的基本信息和bundle生命周期的控制接口。

服务层


一个OSGi 服务就是注册到 OSGi 框架中的一个 Java 对象。注册的时候可以设置这个 Service 的属性。而在获取 Service的时候可以根据属性进行过滤。

Bundle 可以通过 Bundle的上下文去注册Service或去查询Service。

一个提供服务的bundle可以发布POJO作为服务的实体;一个使用服务的bundle可以通过这个注册表找到和绑定服务。

发布服务

为了让别的bundle能发现这个服务,你必须在发布它之前对其进行特征描述。这些特征包括接口的名字(可以是名字的数组),接口的实现,和一个可选的java.util.Dictionary类型的元数据信息。

String[] interfaces =  new String[]{StockListing.class.getName(), StockChart.class.getname()};  
Dictionary metadata =  new Properties();  
metadata.setProperty(“name”, “LSE”);  
metadata.setProperty(“currency”, Currency.getInstance(“GBP”));  
metadata.setProperty(“country”, “GB”);  
ServiceRegistration registration = bundleContext.registerService(interfaces, new LSE(), metadata); 
在上面的代码中,我们得到了 ServiceRegistration 对象,我们可以用这个对象来更新服务的元数据:

registration.setProperties(newMetadata);

也可以直接就把这个服务移除:

registration.unregister();

需要注意的是这个对象不能和其他 Bundle 共享,因为它和发布服务的bundle的生命周期相互依存。

也就是说,如果这个 Bundle 已经不在框架执行环境中存在,那么这个对象也不应该存在了,“皮之不存毛将焉附”就是这个道理。

试想如果这个 ServiceRegistration 共享给了其他的 bundle(具体的说就是其他bundle中存在对这个对象的引用),那么发布服务的那个bundle即使被移除了,由于其他bundle中的引用依然存在,那么垃圾处理机制不会抹去这个对象,这样不但于理不合,而且实际上这个对象也是不可用的,因为这个对象所依存的bundle已经不在了。
代码中的参数new LSE()是一个POJO,这个对象不需要实现任何OSGi类型或者使用标注,只要满足服务约定(这里就是接口)就可以了。

此外,如果在删除发布的服务之前bundle停止了,框架会帮助你删除这些服务。

发现和绑定服务

以下是一个根据实现的接口名称获得的服务的最简单方法:
ServiceReference reference =  
bundleContext.getServiceReference(StockListing.class.getName());

注意这里的reference是服务对象的间接引用,可是为什么要用间接引用而不直接返回那个实际的服务对象呢?

实际上是为了将服务的使用和服务的实现进行解耦,将服务注册表作为两者的中间人,达到跟踪和控制服务的目的,同时还可以在服务消失了以后通知使用者。

这个方法的返回类型是ServiceReference,它可以在bundle之间互享,因为它和使用服务的bundle的生命周期无关。

参考资料


OSGi入门篇:模块层

OSGi入门篇:生命周期层

OSGi入门篇:服务层

OSGi原理与最佳实践
 

OSGi 基本原理的更多相关文章

  1. OSGI中的service依赖关系管理

    众所周知.对于高动态高可扩展的应用,OSGI是一个很好的平台.可是.也因此添加了复杂性.开发中对service的依赖变得复杂. 这也是service的关系管理成为OSGI中一个很重要的部分,我们来看看 ...

  2. OSGi规范的C#实现开源

    这是大约在3-4年前完成的一个C#实现的OSGi框架,实现的过程参照了OSGi规范与与一些实现思路(感谢当时的那些资料与项目),此框架虽然仅在几个小型项目有过实际的应用,但OSGi的规范实现还是相对比 ...

  3. Ognl表达式基本原理和使用方法

    Ognl表达式基本原理和使用方法 1.Ognl表达式语言 1.1.概述 OGNL表达式 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,他是一个 ...

  4. 分享在Linux下使用OSGi.NET插件框架快速实现一个分布式服务集群的方法

    在这篇文章我分享了如何使用分层与模块化的方法来设计一个分布式服务集群.这个分布式服务集群是基于DynamicProxy.WCF和OSGi.NET插件框架实现的.我将从设计思路.目标和实现三方面来描述. ...

  5. Android自定义控件之基本原理

    前言: 在日常的Android开发中会经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件,今天先大致了解一下自定义控件的要求和实现的基本原理. 自 ...

  6. 重新诠释的OSGi规范

    上周五部门开会讨论新一代产品(基于.net Winform)的设计规范,从设计规范慢慢讨论到体系结构等架构存在的问题,诸如菜单.工具条.状态条.界面布局等不能实现配置化和自动化,子系统之间拥有强依赖, ...

  7. HMM基本原理及其实现(隐马尔科夫模型)

    HMM(隐马尔科夫模型)基本原理及其实现 HMM基本原理 Markov链:如果一个过程的“将来”仅依赖“现在”而不依赖“过去”,则此过程具有马尔可夫性,或称此过程为马尔可夫过程.马尔可夫链是时间和状态 ...

  8. 动态令牌-(OTP,HOTP,TOTP)-基本原理

    名词解释和基本介绍 OTP 是 One-Time Password的简写,表示一次性密码. HOTP 是HMAC-based One-Time Password的简写,表示基于HMAC算法加密的一次性 ...

  9. ZooKeeper基本原理

    ZooKeeper简介 ZooKeeper是一个开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等. ZooKeeper设计目的 1. ...

随机推荐

  1. JavaScript var关键字、变量的状态、异常处理、命名规范等介绍

    本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...

  2. HTML5 sessionStorage会话存储

    sessionStorage 是HTML5新增的一个会话存储对象,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据.本篇主要介绍 sessionStorage(会话存储) ...

  3. KV存储系统

    现在的KV存储系统都是分布式的,首先介绍Zookeeper——针对大型分布式系统的高可靠的协调系统. 开发分布式系统是件很困难的事情,其中的困难主要体现在分布式系统的“部分失败”.“部分失败”是指信息 ...

  4. 在ubuntu16.10 PHP测试连接MySQL中出现Call to undefined function: mysql_connect()

    1.问题: 测试php7.0 链接mysql数据库的时候发生错误: Fatal error: Uncaught Error: Call to undefined function mysqli_con ...

  5. 初步认识TDD

    TDD,测试驱动开发(Test Driven Development)是极限编程中倡导的程序开发方法,以其倡导先写测试程序,然后编码实现其功能得名.本文将对TDD有一个较为系统的认识.    基础属性 ...

  6. bzoj1079--记忆化搜索

    题目大意:有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得 ...

  7. Java开发中的23种设计模式详解

    [放弃了原文访问者模式的Demo,自己写了一个新使用场景的Demo,加上了自己的理解] [源码地址:https://github.com/leon66666/DesignPattern] 一.设计模式 ...

  8. android计算每个目录剩余空间丶总空间以及SD卡剩余空间

    ublic class MemorySpaceCheck { /** * 计算剩余空间 * @param path * @return */ public static String getAvail ...

  9. 监控 SQL Server (2005/2008) 的运行状况

    Microsoft SQL Server 2005 提供了一些工具来监控数据库.方法之一是动态管理视图.动态管理视图 (DMV) 和动态管理函数 (DMF) 返回的服务器状态信息可用于监控服务器实例的 ...

  10. 递归实现n(经典的8皇后问题)皇后的问题

    问题描述:八皇后问题是一个以国际象棋为背景的问题:如何能够在8×8的国际象棋棋盘上放置八个皇后, 使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行.纵行或斜线上 ...