- 浏览: 103447 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
Tom.X:
http://osgia.com
OSGI下的web应用开发(5) -
xiaohei520104:
楼组辛苦了,关于OSGi web的demo资料很少,非常感谢你 ...
OSGI下的web应用开发(5) -
shenwu33:
为什么我的server下面 没有eclipseRT
OSGI下的web应用开发(1) -
zhaoweisgz:
谢谢你的共享~
基于virgo环境的OSGI+Maven的web开发代码下载(spring+hibernate+GWT) -
zrz_1989:
楼主我想请教您个问题,如果将项目移植到OSGi平台上,对于we ...
OSGI下的web应用开发(7)
l 什么是模块化
与面向对象一样,模块化的目的也是松耦合,高内聚。我们可以理解为模块化是将对象间的互访做了边界划分,即对一组业务相关的对象进行封装,并且提供可能的更高层次的代码访问隔离机制。
l 物理模块化 VS 逻辑模块化
物理模块化是指应用中的类文件被物理的分割放在不同的模块中,但是每个模块间的互访不受控制,各个模块可以访问模块间的内部对象,只要对象是可访问的。只是是对代码本身进行模块化管理。
例如JAVA中,应用被分为模块A和B,模块B中有一个public对象B.b,该对象可以完全被模块A访问,因为它是public的。
逻辑模块化是指在物理模块化的基础上,对模块进行控制访问;即模块间实现了访问隔离,而这才是我们所说的真正的模块化的概念。
再看回上面的例子,如果B.b没有定义是其它模块可访问的,那么默认A.a是访问不到B.b这个对象的,不管这个对象的访问级别是什么。
l OSGI的作用
在java中,OSGI是一个实现java模块化互访的平台,我们可以理解为是一个更高级的JVM。它提供了逻辑上的模块化控制。
l OSGI对模块的定义
在OSGI中,模块称之为bundle,一个bundle在物理上而言就是一个jar包。Jar包中有一个描述jar包的信息文件,位于jar内部的META-INF目录下的MANIFEST.MF文件。OSGI通过MANIFEST这个文件获取模块的定义信息,比如模块间的互访信息,模块的版本信息等。
Note:对于MANIFEST.MF文件的操作,由于这个文件有很多使用约束,比如一行不能超过72个字符,所以一般都是通过IDE工具对它进行编辑
l bundle里有什么
一个bundle中一般包含如下的东西:
部署描述文件(MANIFEST.MF,必要的),各类资源文件(如html、xml等,非必须的),还有类文件。这与一个普通的jar包没有任何的区别。但是,除此之外,bundle里还可以放入其它的jar包,用于提供给bundle内部的类引用,即bundle内部的lib库。(跟一个war很类似)。
Note:实际上bundle里可以存放任何的内容,但是在bundle内部不会有嵌套的bundle,即上面提到的存放于bundle中的jar包就只会当成是一个普通的jar包,不管这些jar包中是否含有bundle定义的信息
l MANIFEST.MF的定义
MANIFEST.MF位于bundle中的根目录下的META-INF目录下。
一个bundle的必要信息定义如下:
我们称这些内容为bundle的头信息,具备了这4个头信息就是一个bundle
其中,
Bundle-ManifestVersion表示OSGI的参考版本,2代表参考版本使用的是OSGI R4.0+
Bundle-SymbolicName用于作为bundle的ID标识的前缀,一般用模块的顶级包名来命名
Bundle-Version表示bundle当前的版本,并作为bundle的ID标识的后缀
Bundle-Name则是一个可读的bundle的命名定义,没有太大的作用
其它还有很多的头信息的定义,这里就不一一列举了。
头信息的格式:
主要由头属性名称加冒号和各个从句组成,从句间用逗号分隔
Property-Name: clause, clause, clause …
从句的定义:
target; param1(:)=value1; param2(:)=value2 …
target表示头属性对应的值,后面可以带上很多不同的参数对,每个参数分为参数名和参数值,并且都用分号分隔
参数对的定义:
参数分为两种,属性和指令,如果是指令,需要在=号前加上冒号表示是一个指令
attr1=value1
dir1:=value1
头信息的简写形式:
如果头信息的所有target的参数对定义都是一样的,那么可以将target先定义在前面,所有的参数对定义在最后
Property-Name: target1; target2; attr1=value1; dir1:=value1 ….
l Bundle的Identifier
即bundle的ID标识,这个是用来在OSGI中对bundle进行唯一性的定义的。在Bundle被OSGI读取后,OSGI通过对Bundle-SymbolicName和Bundle-Version进行组合,成为一个唯一的ID标识。组合的方式为<Bundle-SymbolicName>_<Bundle-Version>。
Bundle-SymbolicName的命名方式
Bundle-SymbolicName没有任何的命名要求,可以是任意的字符组成,但是一般是用模块的顶级包名来作为它的名称
Bundle-Version的命名方式
Bundle-Version有自己的命名要求,格式为[0-9].[0-9].[0-9].{ConstraintName}
前面都是数字作为版本号,最后一个小数点后的名称是经过命名约束的版本名
例如1.2.3.alpha,1代表大版本号,2代表中版本号,3代表小版本好,而alpha代表小版本中的某个阶段,比如alpha,beta,snapshot,qualifier等,下图展示了版本大小的排序方式
l 代码访问机制设置
JVM环境:
类之间的互访是通过设置classpath来查找的
OSGI环境:
1)bundle内部的classpath
默认是bundle的根目录,但是可以通过头信息来指定bundle内的多个目录
如图所示,通过配置Bundle-ClassPath进行设置,. 代表bundle的根目录,是必须要有的,customPath代表<bundle>/customPath目录,当然,也可以是具体到某个jar文件。将会按顺序查找
2) Export-Package
通过设置Export-Package的头信息进行设置,可以设置多个包,只有在这里定义的包内的类可以被其它的模块进行访问。但是只能访问该包下的,该包的子包的类是不会被曝露的。
例如Export-Package: net.georgezeng.test.modelb.service; version=1.0.0, net.georgezeng.test.modelb.dao; version=1.2.0
3) Import-Package
当某个模块曝露了某些包,那么如果你要引用相应的那个模块下的包的类的话,就需要通知OSGI引入你设置的包到该模块,即在该模块的MANIFEST中定义Import-Package头信息。
例如上面的模块曝露了两个包,分别是service和dao,我们这里假设该模块需要引入service的包来获取当中的类的访问,那么就需要如下设置
Import-Package: net.georgezeng.test.modelb.service; version=1.0.0
这样就能访问该service包下的类了。
Note:该头信息有一个有用的指令resolution,默认值是mandatory,可以设置为optional,当设置为optional时,依赖解析将对其忽略(下面将会提到)
4) DynamicImport-Package
使用此头信息时,OSGI将会扫描该头信息设置的所有包
它只能设置target值,可以多个,并且target值可以使用通配符,例如
DynamicImport-Package: net.gerogezeng.test.*, net.georgezeng.test2 …
OSGI将会扫描net.georgezeng.test下所有的子包,但不包括test包下本身的类,如果要用到test包下的类,就是第二个target所设置的值的方式
Note:使用该头信息时,依赖解析也会对其忽略
5) Require-Bundle
使用Require-Bundle相当于是将被require的Bundle export出来的包全部import
l 关于Export和Import中version属性的定义和匹配
在上面的描述中我们看到了Export和Import中都有一个version的属性定义,该version采用的命名规则与Bundle-Version是一样的,这里主要是说明如何设置它的范围
如图,你可以这样设置
Import-Package: net.georgezeng.test.modelb.service; version=”[1.0.0, 2.0.0)”
Export和Import间的匹配
1) 版本匹配
通过version属性进行设置,通过上图设置的版本的范围比较进行匹配
2) 自定义属性匹配
自定义属性的匹配必须是属性名和属性值都相同,即Import中的属性export中也是有的,且属性值相同
Note:Import-Package的规则也适用于Require-Bundle
l 依赖和解析
何为依赖?
如果BundleA Export了某个包,而BundleB Import了这个包,那么就说BundleB依赖于BundleA
或者BundleA中设置了Require-Bundle的头信息,那么Require-Bundle中的所有相关的target Bundle都被A依赖
Bundle的依赖解析
当OSGI读取Bundle时,Bundle将会被解析,只有当Bundle被正确解析成功,才能被其它Bundle使用或者运行。即OSGI获取Bundle的MANIFEST里的头信息进行检查分析,而这个解析是连锁式反应的。
例如BundleB依赖于BundleA,假设OSGI要使用BundleB,它需要先解析BundleB,而BundllerB因为是依赖于BundleA的,所以BundleA会先于BundleB被进行解析,如果BundleA解析成功,才会继续解析BundleB,如果BundleB也成功解析,那么OSGI就可以正常使用BundleB了,这个过程由于会引起关联的Bundle进行解析,所以是依赖解析。
l DynamicImport vs optional
上面提到了可以通过Import-Package添加resolution指令设为optional或通过DynamicImport-Package进行配置令使得OSGI在进行依赖解析时对其进行忽略。
他们的相同之处都是在运行期间当某个Bundle用到了他们export的包时才会去解析,如果exported的Bundle之前已经解析成功,那么就直接搜索class,如果还未解析过,那么optional只会解析一次,如果失败了,就不会再尝试解析它,直到它已被重新解析过;而Dynamic的方式则是每次都尝试重新解析
l 依赖匹配
Bundle间的依赖需要进行匹配校验,比如bundleA需要某个包,而BundleB曝露了这个包,但是BundleC也曝露了相同的包,那么这时BundleA到底是要依赖哪个呢?这个时候就是通过上面提到的export和import间的匹配来进行校验的。默认会对比version属性,如果import中有自定义属性,那么export中也必须有相应的自定义属性且属性值相同才能匹配成功
匹配的顺序:
1)对version属性进行范围匹配,如果不止一个bundle匹配成功,则进入下一步
2)如果有自定义属性,进行严格的自定义属性匹配,如果不止一个bundle匹配成功则进入下一步
3)查找Bundle-Version更高的Bundle,以最高的版本为主
l Fragment Bundle
一个模块就是一个Bundle,但有时候我们会需要将Bundle在物理上分成多个块,而且让细分出来的块属于同一个模块下,那么这个时候就有了Fragment的概念。
Fragment没办法独立存在于OSGI中,需要依附于某个Bundle下,即有一个Bundle作为宿主。一个Fragment只能依附于一个Bundle。
Note:Fragment本身没有自己的classloader,使用的是Bundle的classloader
l Class的搜索顺序
在了解整个class的搜索路径前,我们需要先了解下面2个内容:
1) Bundle的Classloader
在OSGI环境中,一个Bundle有一个ClassLoader,用于读取bundle内部的类文件
2) boot delegation
在OSGI的配置文件中我们可以配置一个选项用于将需要的包委派给jvm的classloader进行搜索
例如org.osgi.framework.bootdeletation=sun.*,com.sun.*
Bundle请求一个class的顺序如下:
1)如果请求的class来自于java.*下,那么bundle的classsloader会通过父classsloader(即jvm的classloader)进行搜索,找不到则抛错,如果不是java包下的,则直接进入2)
2)如果请求的class非java包下的,那么将搜索boot delegation的设置的包,同样也是通过1)的classloader进行搜索,搜索不到则进入下一步
3)通过Import-Package对应的Bundle的classloader进行搜索,搜索不到则进入下一步
4)通过Require-Bundle对应的Bundle的classloader进行搜索,搜索不到则进入下一步
5)通过Bundle自身的classpath进行搜索,如果搜索不到则进入下一步
6)通过Fragment的classpath进行搜索,如果找不到则进入下一步
7)如果设置了DynamicImport-Package的头信息,将通过扫描DynamicImport-Package中设置的包,然后去相应的export的Bundle中查找,有则返回,没有则抛错,搜索完毕;如果没有设置该头信息,则直接抛错
l Bundle的生命周期
如图,椭圆表示状态,bundle在OSGI中一共可以查看到5个状态,分别是Installed,Resolved,starting,Active,stopping。Uninstalled则是一个虚的状态,即当Bundle不存在于OSGI中时的状态。
OSGI里对Bundle的操作一共有6个,分别是Install,Update,Refresh,Start,Stop,Uninstall
通过这些操作就可以达到不同的状态
如何安装和启动Bundle?
可以通过3种方式:
1)OSGI的配置文件
2)OSGI的shell
3)OSGI的API
关于Resolved
上面提到解析就是从Installed到Resolved间的动作,Resolved表示解析成功,进入已解析状态,此状态下Bundle可以被其它Bundle使用或启动运行Bundle自身
只有在Resolved状态时当调用start命令后才能激活starting状态,并在调用结束后自动转入Active状态,如果starting时有异常则自动返回Resolved状态
Active状态
只有当在Active状态时,调用stop命令才能激活stopping的状态,并在结束后(不管是否有异常)自动转入Resolved状态
Starting和stopping
这两个状态可以交由developer控制,比如对资源进行载入和释放,做一些bundle初始化的事情。
Note:
1)如果Bundle是通过配置文件启动的话,那么Bundle将会通过start level event dispatcher的线程进行starting的操作,并且bunlde间的start是按顺序的,但是由于不是在OSGI的console线程中启动,所以在starting过程中可以对shell进行操作。
2)如果Bunlde是通过shell进行启动的,OSGI将使用shell的当前线程,即OSGI Console线程进行启动,在该状态中shell将无法做任何操作。如果在starting中bundle出现死锁或需要长时间的过程那么将会导致无法对shell进行操作,从而只能选择重启OSGI环境。
3)由于stopping是不可能在OSGI启动时发生的,一般都是在shell下通过stop命令调用发生,这种情况与2)相同。
所以要慎重的考虑starting和stopping的逻辑要如何处理。
在starting和stopping的状态下调用任何相关的操作都是不合理的
关于update和refresh
Update会对bundle内容进行更新,refresh不会对Bundle内容进行更新
1)当Bundle处于Installed状态时,调用update保持状态不变,调用refresh将会自动进行解析,如果成功则进入resolved,否则还是处于installed
2)当Bundle处于Resolved时,调用update命令将会回到installed状态,而调用refresh时会再次解析,成功则自定启动bundle,直到进入active
3)当Bundle处于Active状态时,调用update后如果解析成功将返回active状态,refresh一样
Note:使用refresh会造成依赖解析的发生
关于Activator
Starting和stopping到底是在哪里进行定义呢?OSGI定义了一个Activator对starting和stopping进行操作,这个类是org.osgi.framework.BundleActivator。只要继承该类,并在MANIFEST.MF中定义Bundle-Activator头信息即可实现
关于BundleContext
通过BundleContext我们可以与OSGI框架进行交互,比如获取OSGI下当前的bundle列表。
一个Bundle都有一个对应的BundleContext,当Bundle被start的时候创建且在stop的时候被销毁。每启动一次Bundle都将获得一个新的BundleContext
如何获取BundleContext?
在Activator中,OSGI将会在start和stop方法中传入这个对象
关于event
生命周期的控制总会有一些event可以处理,比如通过实现OSGI提供的listener接口即可,这里不详细熬述
l OSGI的缓存
OSGI对于Bundle的install操作是持久化的操作,即当install某一个bundle的时候,OSGI将会把该bundle进行副本保存,而不再需要当前的bundle的jar包。这是OSGI的默认行为,当OSGI停止再启动时,此Bundle将会自动载入保存的副本。
在update的时候OSGI将会保存一个新的bundle副本,但是老的副本也还在(不过只在当前的OSGI环境下存在了,重启则会找到最新的副本),因为可能有其它的bundle依赖于老副本存在,此时需要使用refresh来进行同步刷新。这种会引起依赖解析再次进行。
如果使用uninstall则bundle的副本不再保存
Note:可以通过添加-clean的启动参数来清理缓存
l Bundle的persistent storage area
OSGI会为bundle开辟一块持久化数据区域,用于给bundle进行资源的存取,这块区域通过BundleContext进行访问,并在uninstall的时候销毁
l OSGI Service
什么是OSGI Service?
我们有了export和import,已经可以很好的管理模块间的代码互访,但是,如果我们只希望曝露接口,而不是实现的话,如何让依赖的Bundle获得接口的实现呢?这个时候我们就需要一种类似服务查找的方式通过OSGI来获得实现了。
所以Bundle有两种角色:生产者和消费者
生产者Bundle通过注册服务将实现注入OSGI中,消费者Bundle则是通过查找服务的方式从OSGI中获得实现。
OSGI目前提供了2种方式用于注册和查找服务:
1)编程式
通过BundleContext进行注册或查找
2)声明式
是OSGI R4.0中引入的新的方式,通过XML文件的配置进行服务的注册和查找
评论
你正在开发bundleI(接口),然后你需要用到其它的bundle,比如bundleC(消费者)和bundleP(提供者),那在你install bundleI的时候bunldeI会去检查相应的依赖bundle,这时会自动install并解析那些bundle
发表评论
-
基于virgo环境的OSGI+Maven的web开发代码下载(spring+hibernate+GWT)
2012-05-16 20:54 8961由于很多朋友在使用我的上一个版本的web开发遇到了非常多的问题 ... -
关于新版本的STS安装新virgo插件的问题
2012-02-28 21:30 6962新的sts已经没有spring dm server tool的 ... -
virgo server使用指南(2)
2011-10-22 15:47 6377这个章节来看看virgo server的目录结构,如有错漏请 ... -
virgo server使用指南(1)
2011-08-27 10:23 9778virgo server的前身是spring dm serve ... -
OSGI下的web应用开发(7)
2011-07-23 12:52 7233现在我们要进入最后一 ... -
OSGI下的web应用开发(6)
2011-07-23 10:04 3629这一节进入Service Interface Bundle和S ... -
OSGI下的web应用开发(5)
2011-07-22 19:04 7703这一节将对Dao Interface Bundle 和 D ... -
OSGI下的web应用开发(4)
2011-07-22 17:28 3779接下来开发Domain Bundle这个模块。这个Bundle ... -
OSGI下的web应用开发(3)
2011-07-21 18:10 6896上节讲了如何对web应用 ... -
OSGI下的web应用开发(2)
2011-07-21 13:28 5305前面已经讲了开发环境 ... -
OSGI下的web应用开发(1)
2011-07-20 21:33 10080本文将详细的展示OSGI下如何开发一个基于spring的web ... -
OSGI知识小计(3)- bundle的总结
2011-04-26 20:37 59(1)bundle的identifier 在 ... -
OSGI知识小计(2)
2011-04-24 17:15 32(1)OSGI framework的类搜索顺序: 如 ... -
OSGI知识小计(1)
2011-04-22 21:03 71今天学习了OSGI的一些入 ... -
如何安装OSGI的模块(How to install bundle into OSGI Container)
2011-04-20 00:16 64今天开始学习OSGI的知识 ...
相关推荐
### OSGi 学习心得与Java开发 #### 一、初识OSGi与学习路径 **1. 了解OSGi的基本架构与精神** - **资料来源:** COSCUP2008会议中try的OSGi简介演讲(投影片、影片一、影片二)。 - **学习目标:** 通过观看这些...
OSGI(Open Services Gateway Initiative)是一种开放标准,用于创建可模块化的Java应用程序。它提供了一种灵活的框架,使得开发者可以构建、部署和管理模块化组件,这些组件被称为服务或bundle。OSGI的核心理念是将...
OSGI(Open Services Gateway Initiative)是一种模块化系统和Java服务框架,它允许应用程序由一系列可独立更新和替换的模块组成,这些模块称为“bundle”。在本实例中,我们将探讨如何利用OSGI技术来开发Eclipse...
OSGi(Open Services Gateway Initiative)是一种Java模块化系统,它为开发人员提供了一种动态、模块化的运行时环境。在OSGi中,应用程序被分解为称为“bundle”的独立单元,这些bundle可以相互依赖并独立地加载、...
OSGI(Open Services Gateway Initiative)是一种Java模块化系统,它允许开发者将应用程序分解为一系列可独立部署、更新和交互的服务。林昊所著的《OSGI实战》与《OSGI进阶》是深入理解OSGI技术的重要参考资料,适合...
OSGI组件编程是一种在Java平台上构建模块化应用程序的方法,它由OSGi联盟制定标准,并被广泛应用于企业级软件开发,尤其是对于需要高度可扩展性和动态性的系统。在本教程中,我们将深入探讨如何使用Eclipse和Equinox...
OSGi规范中文版是一本全面介绍OSGi技术的书籍,它不仅涵盖了OSGi技术的基础知识,还详细介绍了OSGi的内部结构和工作原理,对于想要深入学习和应用OSGi技术的开发者而言,是一本非常有价值的参考书。 ### OSGi规范的...
OSGi(Open Services Gateway Initiative)是一种Java平台上的模块化服务框架,它定义了一种标准,使得开发者能够构建可互操作的、动态的、模块化的软件系统。OSGi的核心概念是基于Java的模块化,它的主要目标是为...
OSGI(Open Services Gateway Initiative)是一种开放标准,用于创建模块化和动态的Java应用程序。它为Java开发人员提供了一个框架,使他们能够构建可热插拔的组件,从而实现更灵活、可扩展和可维护的软件系统。在本...
资源名称:OSGI原理与最佳实践内容简介:国内第一本OSGi图书OSGi国内推广者林昊多年经验的结晶涵盖OSGi从入门到深入的知识体系引领OSGi国内研究和普及本书基于作者多年使用OSGi的经验而编写,涵盖了OSGi从入门到深入...
Spring OSGi是Spring框架与OSGi(Open Service Gateway Initiative)规范相结合的一种技术,它允许在OSGi容器中运行和管理Spring应用。OSGi是一种模块化系统,为Java应用程序提供了动态部署、版本控制和依赖管理的...
OSGi(Open Services Gateway Initiative)学习笔记(一) 在IT领域,OSGi是一种模块化系统和Java服务平台,它提供了一种动态管理软件组件的能力。本文将深入探讨OSGi的基本概念、架构以及如何使用它来构建可扩展和...
OSGI,全称为Open Service Gateway Initiative,中文名为开放服务网关倡议,是一个为Java平台设计的模块化系统和动态服务框架。它定义了一种标准的模块化体系结构,允许Java应用程序由可独立更新和替换的模块(称为...
利用R-OSGi实现分布式OSGi应用 本文通过介绍传统 OSGi 应用程序及 R-OSGi 的实现方式入手,阐述了 R-OSGi 对于 OSGi 规范的实现方式。然后通过一个简单的功能实现由浅入深地讲述传统 OSGi 和 R-OSGi 上的两种不同...
OSGI(Open Services Gateway Initiative)是一种开放标准,用于创建模块化和可扩展的Java应用程序。它提供了一种灵活的框架,允许开发人员将应用程序分解为独立的模块,这些模块称为服务。OSGI的核心是它的模块系统...
标题中的“tomcat嵌入OSGI容器”是指在Apache Tomcat服务器中集成OSGI(Open Service Gateway Initiative)框架,使得Tomcat能够支持模块化的应用程序部署和管理。OSGI是一种Java平台上的服务导向架构,它允许动态地...
《企业OSGi实战》一书是OSGi企业应用的权威指南,它不仅涵盖了OSGi在企业环境中的应用,还提供了Java企业版(Java EE)与OSGi特性的融合方法。本书详细介绍了模块化编程的重要性,以及OSGi如何强化Java的模块化能力...
这个压缩包包含了关于OSGI的重要文档,分别是“OSGi R4核心规范文档”、“OSGi服务文档”以及“OSGi-最佳原理与实践”(王昊编著)。下面将详细介绍这些文档所涵盖的关键知识点。 首先,"OSGi R4核心规范文档"是...
OSGi(Open Services Gateway initiative)是一种Java动态模块化系统规范,其核心思想是将应用分割成一系列的 bundles(模块),每个 bundle 都可以独立地安装、启动、停止、更新,而不会影响到其他 bundles。OSGi ...
网上收集的OSGI资料. 包括: OSGi原理与最佳实践(精选版).pdf OSGI实战和源码.rar osgi进阶.pdf Introduce.OSGi.ppt OSGi.in.action.ppt r4.cmpn.pdf r4.core.pdf r4.enterprise.pdf