借助网上的一些资料,对OSGi有了一些了解,将到目前的一些粗浅认识记录如下,由于自己对J2EE比较熟悉,所以借助与J2EE的对比来认识OSGi。
Module
OSGi中具体实现Module的单位是bundle,一个bundle就是一个jar文件,其中包含所需的类文件和资源文件,同时必须包含一个描述文件;每个bundle都可以被独立打包、部署。看到这里,你是否会觉得跟J2EE中的WAR定义很类似?
单从形式上来看,它们的确非常相似,而且它们的区别主要在于:
1)J2EE的WAR文件的粒度很大,是以应用为单位的;而OSGi bundle的粒度则相对小很多,以一组服务为单位,一个OSGi应用将包含多个bundle。
2)最重要的差别是,bundle之间可以通过共享java package、发布或者引用服务进行协作。而Web应用之间几乎是不存在协作的,起码在定义上没有。
3)在J2EE中,可以将多个war文件打包成为一个ear文件进行部署,而OSGi/bundle则没有这种"Application"的概念,每个bundle都必须独立部署。
Life Cycle
bundle拥有自己的生命周期,可以被安装、启动、激活、停止等,这一点与J2EE中的WAR也非常相似。不过由于不存在协作关系,WAR的生命周期相对简单,只关心自己能否启动则可。而bundle在被激活之前,必须保证其依赖的其他bundle已经存在。
Class Loading
在J2EE Servlet规范中,对ClassLoader的着墨不多,不过目前各产品的实现都比较类似,就是每个WAR文件有一个独立的ClassLoader。如下图,由于WebApp1和WebApp2使用不同的ClassLoader,因此它们可以使用同一个Java Class的不同版本:
+-----------------------------+
| Bootstrap |
| | |
| System |
| | |
| Common |
| / \ |
| Catalina Shared |
| / \ |
| WebApp1 WebApp2 |
+-----------------------------+
(from http://tomcat.apache.org/tomcat-4.1-doc/class-loader-howto.html)
在这张图中我们可以看到Catalina用独立的ClassLoader,这是一个进步。早期很多人都遇到过这样的问题,自己的应用中采用了某个开源软件,部署的时候却无法正常运行。其原因是服务器已经采用了该开源软件的较老版本,而自己的应用却依赖与新版本。新版本的Tomcat则把自己依赖的类库放在Catalina分支,这样这些类库对所有WebApp都不可见。同时由Shared负责的类库则是所有WebApp都能够用到。
这样的ClassLoader结构对于WebApp来说已经相当不错,但是仍然有一个问题没有解决,那就是如果WebApp1需要用到WebApp2的类怎么办?对于WebApp来说,这种需求的确相当罕见,因为应用与应用之间一般不会出现之间的类引用。但是对于一个应用中的多个模块,相互引用则是再正常不过了。
论坛上正好有个帖子“有关于classloader的思考(或者说是困惑)”整理了这方面的需求,我则无需重复。楼主edge_hh的问题用OSGi则可以很简单解决:
1. 在模块A的配置文件说明"Export-Package: demo.a.httpservice"
2. 在模块B的配置文件说明"Import-Package: demo.a.httpservice"
3. 将所有httpservice接口需要的定义放置在模块A的demo.a.httpservice下
这样就可以了。这就是OSGi的特别之处,bundle的CloassLoader是平级的,但平级的CloassLoader之间可以共享Java Package。
Delcare Services
在edge_hh的帖子中,他没有明确提出的一个问题是,模块B是如何调用模块A的服务?
在Java WebApp中,是不存在跨WebApp的服务调用,forward和include操作都是局限在同一个WebApp中。EJB中用<ejb-ref>来描述对EJB的引用,不过这种引用方式就如人们对EJB2的批评一样,复杂、不方便使用。
实际上在服务引用这方面,大家更加熟悉的应该是Spring的方式,如下:
<beans>
<bean id="ModuleA" class="demo.a.httpservice.HttpService"/>
<bean id="ModuleB" calss="demo.b.Consumer">
<property name="httpService">
<ref bean="ModuleA"/>
</property>
</beans>
不过在这种场合下Spring存在的问题有:
1. Spring没有"module"的概念,难以说明“一个module包含多个service”这样的情况
2. Spring的DI是静态的,一旦建立就不会更改。而在模块化的程序中,一个模块在运行时也有卸载、重新部署的时候。Spring无法处理这种情况。
让我们来看看OSGi的做法,下面的配置代码来自《OSGI 实战》的例子:
1)声明服务:
<?xml version="1.0" encoding="UTF-8"?>
<component name="DBValidator">
<implementation class="org.riawork.demo.service.user.impl.DBValidatorImpl"/>
<service>
<provide interface="org.riawork.demo.service.user.Validator"/>
</service>
</component>
2)引用服务:
<?xml version="1.0" encoding="UTF-8"?>
<component name="LoginServlet">
<implementation class="org.riawork.demo.web.servlet.LoginServlet"/>
<reference name="ValidatorService" interface="org.riawork.demo.service.user.Validator" bind="setValidator" unbind="unsetValidator" policy="dynamic" cardinality="0..1"/>
<reference name="HttpService" interface="org.osgi.service.http.HttpService" bind="setHttpService" unbind="unsetHttpService" policy="dynamic"/>
</component>
其中特别的部分是bind和unbind的设定。通过bind和unbind,服务消费者能够知道所需服务对应模块的启动和停止,从而实现了DI的动态绑定。
"OSGi technology is the dynamic module system for Java!"
在学习OSGi之前,盛名之下,总觉得OSGi是很复杂的技术;然而在初步了解OSGi后,又觉得它非常简单,或者说是如此的清晰明了。我初步认识到OSGi的主要好处是:
1)明确定义了Moduel/Service的。
“我们的应用/系统是模块化的”,这是一句常常能听到的话语,然而个模块的具体实现方式恐怕每个应用都不尽相同,这种情况非常不利于开发团队积累可重用的模块。现在通过OSGi的严格定义,有望形成一个标准的模块市场,Eclipse的Plug-in就是一个很好的例子。即便只是在公司范围内形成模块仓库,都将对开发效率有极大提高。当然一个相当规模的模块市场,必然是依赖于一套设计良好的Service接口的。
2)运行时的动态性。
服务具体由哪个模块提供,模块的安装、启动、停止、卸载,这些都可以在运行时指定,并且随时更改。这样的情况下,应用的动态性就取决于你的想象力了。举一个实在的例子,我们无需重新启动整个应用,就能够对应用进行打补丁、升级。
推荐读物:《OSGi 实战》Opendoc,喜欢其中清晰明了的例子。
分享到:
相关推荐
OSGI(Open Services Gateway Initiative)是一种开放标准,用于创建模块化...通过阅读这本书,你可以获得对OSGI的全面认识,从理论到实践,从而在你的项目中更好地利用OSGI的优势,构建更加灵活、可维护的Java应用。
- **学习成果:** 对OSGi有一个初步的认识,包括其模块化设计思想和服务平台理念。 **2. 深入学习OSGi基础应用** - **资料来源:** 《OSGi in Practice》电子书的前4章。 - **学习目标:** 掌握OSGi的基础应用细节...
- **背景**: 作者自工作以来一直关注插件体系结构,从早期接触ant、maven等工具开始,逐渐认识到模块化的重要性。 - **目标**: 通过本书籍,作者旨在分享其在OSGI领域的实践经验,特别是使用Equinox框架的心得体会。...
**OSGI_Assignment** 在Java世界中,OSGi(Open Services Gateway Initiative)是一个模块化系统和Java服务平台,它提供了一种动态管理软件...这个过程不仅能提升你的编程技能,还能让你对模块化系统有更深的认识。
标题 "书籍配套的源代码" 暗示了这些文件是与某本IT技术书籍相关的编程...通过Eclipse这样的集成开发环境,读者可以方便地导入和运行这些代码,观察它们的运行效果,从而加深对OSGi技术及其在实际项目中的应用的认识。
### Spring Dynamic Modules (Spring DM...通过上述介绍,我们对 Spring DM 的基本概念、安装步骤以及关键特性有了较为全面的认识。无论是对于初学者还是有经验的开发者来说,Spring DM 都是一个值得深入了解的技术栈。
通过这些知识点,开发者可以对Eclipse插件开发有一个全面的认识,从基础知识到高级概念,从技术实现到版权声明,都有涉及。这有助于开发者在遵循版权政策的同时,高效地学习和实践Eclipse插件开发。
本书从认识JUnit、不同的测试策略、JUnit与构建过程、JUnit扩展4个方面,由浅入深、由易到难地对JUnit展开了系统的讲解,包括探索JUnit的核心、软件测试原则、测试覆盖率与开发、使用stub进行粗粒度测试、使用mock...
《JUnit实战(第2版)》从认识JUnit、不同的测试策略、JUnit与构建过程、JUnit扩展4个方面,由浅入深、由易到难地对JUnit展开了系统的讲解,包括探索JUnit的核心、软件测试原则、测试覆盖率与开发、使用stub进行粗粒度...
Apache Karaf是一款轻量级的Java企业服务框架(Service-Oriented Architecture,SOA)容器,它是基于OSGi(Open Service Gateway ...结合源代码和书中的讲解,实践操作和分析,将使你对Apache Karaf有更全面的认识。
它提出了一种在OSGi层之上运行的模块化体系结构,使其可以通过插件高度扩展。 它支持多种协议绑定,例如HTTP和CoAP。 提供了各种互通代理,以实现与供应商特定技术(例如Zigbee和Phidgets设备)的无缝通信。 ...
【深入探讨 Java 类加载器】 Java 类加载器是Java虚拟机(JVM)的核心组成部分,它的主要任务是将Java类的字节码加载到JVM中以便执行...无论是解决运行时问题还是设计复杂的系统架构,都需要对类加载器有深刻的认识。
这可能影响到应用的并发性能,需要开发者对事务超时和会话管理有充分的认识。 4. [HHH-8022]:提到回归问题,即在Hibernate 4.2.0 CR1中返回的`REFCURSOR`在本正式版中出现问题。开发者在使用命名查询时需要注意这...
它以OSGi(开放服务网关接口)为核心,为用户提供了一个模块化、动态的运行时环境,能够运行和管理可动态替换的组件。ServiceMix支持JBI(Java业务集成规范)标准,因此能够和其他遵循JBI标准的ESB系统进行互操作。 ...
- 选择`Create an OSGi bundle manifest`选项来启用OSGi支持,这是Eclipse 3.0及以上版本的动态加载标准。 2. **配置插件属性**: - 在`New Plug-in Project`向导中,选择创建一个RCP应用(勾选`Would you like ...
最后,本书可能还会涵盖一些高级主题,如OSGi服务、Eclipse IDE的性能优化以及Eclipse与云计算、大数据等现代技术的结合。这将使读者对Eclipse的潜力有更全面的认识。 总之,《Eclipse In Action》是一本全面而深入...
在开始之前,我们需要对Java有基本的认识。Java是一种面向对象的编程语言,由Sun Microsystems(现为Oracle公司)于1995年发布,其设计目标是“一次编写,到处运行”。它的语法简洁且强类型,有着丰富的类库,特别...