osgi笔记
Bundle-Classpath可以实现内嵌jar。
一个Bundle的Activator不需要进行Export
一个Package中的类被两个ClassLoader加载,包中的Private class对于两个ClassLoader之间是相互不可见的。
Manifest语法: name: value,我们称之为一个条目,Manifest文件有不受限制的条目个数,其中name是不区分大小写,可以包含字母数字,下划线,中划线,Value可以包含除子\r, \n之后的所有字符,name和value之间必须用一个冒号和一个空格分隔开,一行不能超过72个字符,超过72字符部分需要从下一行,以一个空格开始继续写,
Manifest中空行或者全是空格的行用来划分属性group。osgi只取第一个group中定义的name value。
Osgi Manifest的条目定义形式如下,value中有多个clause(用","分隔),每个clause中包含有target,directive和attribute三部分。其具体语法请参考OSGi In action一书或者OSGI规范。不过一般不需要纠结于这一点,看了下面的一些例子相信大部分读者都能“不攻自破”,但书面表达起来的确是个问题。
Property-Name: target1; dir1:=value1; attr1=value2,
target2; dir1:=value1; attr1=value2,
target3; dir1:=value1; attr1=value2
如果value中包含有空格或者分隔符“,” 和“;”的话,需要用括号来括起来
如果多个target之间有相同的attribute和directive的话,可以采用下面的简写形式:
Property-Name: target1; target2; dir1:=value1; attr1=value2
下面是一些human-readable bundle metadata。Osgi framework将它们忽略:需要注意的是由于历史原因Bundle-Name并不是一个用于Bundle Identification的Manifest Attribute。
Bundle-Name: Simple Paint API
Bundle-Description: Public API for a simple paint program.
Bundle-DocURL: http://www.manning.com/osgi-in-action/
Bundle-Category: example, library
Bundle-Vendor: OSGi in Action
Bundle-ContactAddress: 1234 Main Street, USA
Bundle-Copyright: OSGi in Action
Bundle-SymbolicName和Bundle-Version用于唯一标识一个Bundle。它们在Require-Bundle中被使用,大多数情况下,osgi还是在使用package作为import的标识的。
Bundle-SymblicName的value类似于java的包名,用"."来分隔。Bundle-Version的value遵循osgi version的命名规则
例如:
Bundle-ManifestVersion: 2 // 这个也会起标识作用,但目前它仅有2是合法的。
Bundle-SymbolicName: org.foo.shape
Bundle-Version: 2.0.0
Osgi中关于代码可见性的metadata有以下几种信息:这里不作翻译,直接贴上书中的原文:
Internal bundle class path: The code forming the bundle
Exported internal code: Explicitly exposed code from the bundle class path for sharing with other bundles
Imported external code: External code on which the bundle class path code depends
Bundle-ClassPath用于表示Bundle内部类加载时的ClassPath,类似于定义内部可见性,注意这些ClassPath都是相对于Bundle jar文件内部的,我们还可以在Bundle中加入内嵌的jar包,如下:
Bundle-ClassPath: .,other-classes/,embedded.jar
Bundle-ClassPath的缺省值是".",也就和非osgi环境中的jar包的加载规则一致了。
Export-Package用于暴露bundle内部的类,多个包名之间用逗号隔开","同时,包名可以用";"隔开并加上限定的Attribute,因此多个Bundle可能导出同样的包名,这时候需要其它信息加以限定,并且如果多个包名所有的限定属性都一致的话,采用采用省略的写法,如下:
Export-Package: org.foo.shape; vendor="Manning", org.foo.other;
vendor="Manning"
和下面的写法效果一致
Export-Package: org.foo.shape; org.foo.other; vendor="Manning"
除此之外,osgi定义了一个专门的限定属性version,其值必须遵循osgi version的规范。另外包名下的子包是不会被导出的。
Import-Package用于导入在运行时bundle所依赖的类。但java.*开头的类比较特殊,它自动地对所有的bundle都是可见的,因此我们不需要也无法插手这一点。Import-Package和Export-Package的写法上基本一致,但是Import-Package可以指定version的范围,比如:
Import-Package: org.osgi.framework; version="[1.3.0,2.0.0)"
version定义规范如下:
在没有version限定的情况下,version默认为0.0.0,因此version>=0.0.0的匹配到的包都有可能被选择。
1、注意在有多个版本的Export-Package符合version要求的话,那么osgi将会选择最高版本那个,比如servlet bundle提供javax.servlet; version="2.4.0"而tomcat bundle提供了javax.servlet; version="2.5",那么osgi将使用tomcat中提供的类。如果servlet bundle已经先于tomcat bundle被使用,那么将使用servlet bundle中的类,即使它的版本号比较低。
2、如果有两个bundle提供的版本号也相同的话,那么选择,最先被install的那个bundle。
Use directive:上面两点在解决类不一致问题上还是不足的,对于在方法名上暴露了import进来的类的情况下(osgi in action page61-63),需要用uses:=import.package.name这一条directive来解决,uses:=import.package.name用于保证其它bundle import这个bundle的Export-Package的时候,转为使用这个Bundle所import的import.package.name,上面这句话不知道怎么表达哈,贴上原书的图:
其实Http Service这个Bundle在Export-Package中,通过方法的签名暴露了从Servlet API bundle import进来的javax.servlet.Servlet和javax.servlet.ServletContext:
package org.osgi.service.http;
import javax.servlet.Servlet;
public interface HttpService {
void registerServlet(Sting alias, Servlet servlet, HttpContext ctx);
}
那么在Http Servlet Bundle中使用uses:=javax.servlet时候,将传递性地使Http Client也转为使用Servlet API Bundle中export的javax.servlet; version="2.3.0",从而保证了类的一致性:
Export-Package: org.osgi.service.http;
uses:="javax.servlet"; version="1.0.0"
Import-Package: javax.servlet; version="2.3.0"
不过osgi framework并不能为我们解决所有的问题,所以这种情况下我们自己可以手动解决的就不要偷懒了。
类搜索的顺序:
1、如果类名以java.开头,那调用父加载器进行加载,如果找不到将抛出ClassNotFoundException等异常。
2、如果这个类属于Import-Package中的一员,那么,委托给对应的外部的Bundle进行加载。
3、最后搜索Bundle-ClassPath
关于osgi模块化的高级特性:
importing exported packages, implicit attributes, mandatory attributes, class filtering, and duplicate exports.
Importing exported packages: 这种情况多发生在接口与实现打包在一起,而又希望osgi环境中可以从别的bundle中拿到接口的实现者,而且它们之间可以进行交互。比如书中所描述的情况:
Bundle A, Bundle B 都导出了javax.servlet,Bundle A import javax.servlet.Servlet,而且A在使用javax.servlet.Servlet时候希望能同时在B和C之间传递,交互。
那么,针对C有两种解决方案:
1、删除C中的javax.servlet,import B中的。
2、不删除C中的,并且导出javax.servlet。
方案1的话,C将依赖于B,在缺少B的环境将无法使用。
方案2的话,A中的javax.servlet.Servlet无法在B,C之间传递,否则将引起ClassCastException。
针对这个情况,osgi提供了一个import exported package方案,我们可以在C中使用import exported package,如下,Import-Package 和Export-Package可以有不同的Version,表明C可以更低版本的javax.servlet下工作,这并不是错误:
Export-Package: javax.servlet; version="2.4.0"
Import-Package: javax.servlet; version="2.3.0"
Implicit export attribute Export-Package(隐性携带的属性):
在Export-Package的时候,OSGi framework隐性地在导入的包中附加上bundle-symbolic-name(值为Bundle-SymblicName)和bundle-version(值为Bundle-Version)属性:
Bundle-ManifestVersion: 2
Bundle-SymbolicName: my.javax.servlet
Bundle-Version: 1.2.0
Export-Package: javax.servlet; javax.servlet.http; version="2.4.0" 等同于(下面展示用,不能像下面直接在Manifest Export-Package中写bundle-symbolic-name和bundler-version属性,否则会在install bundle时候抛出异常) Bundle-ManifestVersion: 2
Bundle-SymbolicName: my.javax.servlet
Bundle-Version: 1.2.0
Export-Package: javax.servlet; javax.servlet.http; version="2.4.0";
bundle-symbolic-name="my.javax.servlet"; bundle-version="1.2.0"
同时在Import-Package的时候指定bundle-symbolic-name和bundle-version:
Import-Package: javax.servlet; bundle-symbolic-name="my.javax.servlet"; bundle-version="[1.2.0,1.2.0]"
注意应该尽量避免implicit exported package,因为正常的Export-Package 属性也可以完成类似的工作。
Mandatory directive用于指定Export-Package中,Import-Package在进行bundle 匹配的时候必须进行匹配的属性,如果属性不存在或者匹配不上,那么将不会import 这个package。比如下面的例子:
Export-Package: javax.servlet; version="2.4.1"; private="true";
mandatory:="private"
那么在Import-Package的时候必须指定这个private属性才能import成功:
Import-Package: javax.servlet; version="[2.4.0,2.5.0)"; private=true
Exclude Directive用于从Export-Package中过滤掉(屏蔽)一些类,如下,org.foo.service.Util将不会被导出,Exclude Directive支持通配符*:
Export-Package: org.foo.service; version="1.0.0"; exclude:="Util"
同样Include Directive用于指定Export-Package中进行导出的类:
Export-Package: org.foo.service; version="1.0.0"; include:="Service*"
Duplicate Export和Include Directive, Export Directive结合用于实现向不同的bundle导出不同的类。
resolution directive用于表明依赖是可选的,在没有Bundle export相应的package情况下也能完成bundle resolve过程,ClassNotFoundException,找不到这些类的情况下该bundle 也可以正常完成工作,比如一些日志服务类。
Dynamic Import 用于解决SPI问题。
DynamicImport-Package: javax.servlet.*; version="2.4.0"
DynamicImport-Package和resolution:=optional有以下两点相同之处 :
Optional/dynamic imports never cause a bundle to be unable to resolve.
Your bundle code must be prepared to catch ClassNotFoundException s for the optionally/dynamically imported packages.
Require-Bundle: 用于导入另一个bundle中所有的Export-Package。
关于存在Require-Bundle时候的类搜索顺序:
1、如果类名以java.开头,那调用父加载器进行加载,如果找不到将抛出ClassNotFoundException等异常。
2、如果这个类属于Import-Package中的一员,那么,委托给对应的外部的Bundle进行加载。
3、如果这个类属于Require-Bundle中的,那么将从Require-Bundle目标中进行搜索,如果找到了即返回,如果没有找到则继续从下一个Require-Bundle目标开始搜索。
4、如果3中找不到的话,从Bundle-ClassPath中搜索。如果没有找到的话继续步骤5
5、如果类所在的包isn't exported or required(这里的意思不是很清楚)的话,开始对DynamicImport-Package进行匹配,如果匹配到了,则委托给export这个package的Bundle。如果找到了,则返回,如果最后还是找不到只好抛出异常了。
同样Require-Bundle也可以使用resolution:="optional" directive,并且可以使用visibility进行reexport,比如A require-bundle B那么B中的Export-Package将会添加在Bundle A的Export-Package列表中。
最后一个特性是Fragment Bundle,在Fragment Bundle中,有Host和Fragment两种角色,Host Bundle中对Fragment Bundle是不可知的,但Fragment Bundle中必须声明它所属于的Host Bundle(通过Fragment-Host):(注意只能声明一个Host Bundle,不能声明多个)
Fragment-Host: org.foo.hostbundle; bundle-version="[1.0.0,1.1.0)"
Host Bundle中无须声明任何关于Fragment Bundle的信息,没有Fragment-Host声明的Bundle默认就是一个Host Bundle。
另外Fragment Bundle中不能定义Bundle-Activator,因为它不是一个独立的bundle。它必须依存于Host Bundle。
注意,Fragment-Bundle和Host Bundle使用同一个ClassLoader
最终在查找类的时候的搜索顺序:
1、如果类名以java.开头,那调用父加载器进行加载,如果找不到将抛出ClassNotFoundException等异常。
2、如果这个类属于Import-Package中的一员,那么,委托给对应的外部的Bundle进行加载。
3、如果这个类属于Require-Bundle中的,那么将从Require-Bundle目标中进行搜索,如果找到了即返回,如果没有找到则继续从下一个Require-Bundle目标开始搜索。
4、如果3中找不到的话,从Bundle-ClassPath中搜索。如果没有找到的话继续步骤5
5、搜索已经installed的Fragment Bundle的Class path,如果查找到了则返回,如果没有找到则继续直到查找完所有的Fragment Bundle,如果最后仍然没有找到则开始步骤6
6、 如果类所在的包isn't exported or required(这里的意思不是很清楚)的话,开始对DynamicImport-Package进行匹配,如果匹配到了,则委托给export这个 package的Bundle。如果找到了,则返回,如果最后还是找不到只好抛出异常了。
osgi笔记的更多相关文章
- OSGI.NET 学习笔记(一)
1. 关于OSGI.NET 在介绍 OSGI.NET 前先介绍下OSGi, OSGI全称为Open Service Gateway Initiative,它一方面指由IBM.Oracle.BEA.SA ...
- 《深入理解OSGi:Equinox原理、应用与最佳实践》笔记_1_运行最简单的bundlehelloworld
<深入理解OSGi:Equinox原理.应用与最佳实践>笔记_1_运行最简单的bundlehelloworld 买了周大大的OSGI的书看 先前完全没有基础 就靠这本书看看学学 顺便记一些 ...
- OSGi.NET 学习笔记
OSGi.NET 学习笔记 [目录] 持续更新和调整中,本人学习笔记,非官方文档,难免疏漏,仅供参考. OSGi.NET SDK下载地址. 前言及环境准备 模块化和插件化 概念 实例 小结 面向服 ...
- OSGI入门笔记
OSGI框架为Java定义了一个动态模块化系统,它使你可以更好地控制代码结构,动态管理代码的生命周期,并且提供了代码写作的松耦合方式:更值得称道的是,它的规范文档描述详尽.--<OSGI实战&g ...
- OSGI.NET 学习笔记--架构篇
关于osgi.net ,想必大家也听说过,以下是自己在学习osgi.net 过程中整理出来的内容,供大家学习参与使用. 1. UIOSP 开放工厂框架架构 开放工厂所有插件基于OSGi.NET面向服 ...
- OSGI.NET 学习笔记--应用篇
关于osgi.net ,想必大家也听说过,以下是自己在学习osgi.net 过程中整理出来的内容,供大家学习参与使用. 1. OSGI.NET 与UIOSP OSGi是Open Service Ga ...
- 《深入理解OSGi:Equinox原理、应用与最佳实践》笔记_2_建立开发环境
本文对应书本5.1.3的内容 书本中通过CVS下载的源码 但是笔者实践的时候发现无法下载...地址已经失效了(也许是笔者的失误输错地址所致) 可以用git下载 地址是: http://git.ecli ...
- JVM笔记11-类加载器和OSGI
一.JVM 类加载器: 一个类在使用前,如何通过类调用静态字段,静态方法,或者new一个实例对象,第一步就是需要类加载,然后是连接和初始化,最后才能使用. 类从被加载到虚拟机内存中开始,到卸载出内存为 ...
- OSGi.NET使用笔记
一手资料来源于“开放工厂”,以下程序将会引用到一个核心文件UIShell.OSGi.dll 目前我对于OSGi这个框架的理解就是,主程序搜索并加载插件,以插件方式开放,便于扩展. 现在开始正式的旅程. ...
随机推荐
- Linux 防火墙开放特定端口 (iptables)
iptables是linux下的防火墙,同时也是服务名称. service iptables status 查看防火墙状态 service iptables start ...
- DataList:HTML5中的input输入框自动提示宝器
DataList的作用是在你往input输入框里输入信息时,根据你敲进去的字母,自动显示一个提示下列列表,很像百度或谷歌的搜索框的自动提示,在飞机票火车票的搜索页面上也有这样的效果.它是HTML5里新 ...
- ASP.NET MVC中多种ActionResult用法总结
最近一段时间做了个ASP.NET MVC4.0的项目,项目马上就要结束了,今天忙里偷闲简单总结一下心得: 1. 如果Action需要有返回值的话,必须是ActionResult的话,可以返回一个Emp ...
- C语言拾遗
1. 没C++那么恶心的const C语言中的const修饰符用于修饰一个变量是const属性的.被C语言的const修饰的变量具有只读属性,并且不能被修改. const修饰的变量 != 常量,con ...
- PAT (Advanced Level) Practise:1001. A+B Format
[题目链接] Calculate a + b and output the sum in standard format -- that is, the digits must be separate ...
- 请求网络get
package com.baidu.net; import java.io.IOException; import org.apache.http.HttpEntity;import org.apac ...
- DNS学习笔记之DNS理论知识
DNS: Domain Name System (将域名和ip地址相互转化) 域名是一个范围,例如baidu.com,.com.而www.baidu.com是个主机名,即FQDN: Full Qual ...
- canvas 画字
用canvas画字还是头一回,要想和UI设计的画的一模一样还是真有些苦难,不过现在实现的效果已经很像了. <!--通过字体文件引入字体--><style>@font-face ...
- 微信Oauth2.0鉴权 40029 问题
前阵子出了这个问题,具体表现为,在获得用户授权时,有时会出现 40029 code 无效或超时 问题.在网上查询后,大多数人说是因为微信请求了两次url,导致第二次失效,而第一次被终止了. 现在找到了 ...
- 数据库备份Sql
今天学习心得: 数据库备份语句: backup database ZhiHuiGongDi To disk = 'D:\zhihuigongdi20150824.bak'