1、Spring

Spring是一个开源框架,是于2003 年兴起的一个轻量级的Java 开发框架,它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。然而,Spring的用途不仅限于服务器端的开发,从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架

2、OSGi

OSGi的名称来源于其开源组织的名称Open Services Gateway initiative,OSGi是一个标准,它致力于提供给Java项目一个模块化的底层环境,以及一系列通用的服务(Service)。和普通的JVM程序相比,OSGi的程序天生拥有动态模块的特点,不同的模块(OSGi里称之为Bundle)有着独立的生命周期,可以独立进行安装、启动、停止、卸载的操作,模块间的依赖性管理也由OSGi提供。你可以看出,OSGi非常适合需要进行Plugin管理的项目,一个典型的成功案例就是Eclipse和它众多的Plugin。OSGi标准还规范了一系列我们常间的操作,日志、配置文件、事件队列、Web开发、JPA&JDBC等等,大部分部署OSGi标准的框架都提供了这些服务,这样一方面规范了我们代码的结构,一方面节约了我们开发的时间。

目前基于OSGi的框架大概有4个:Knopflerfish, Apache Felix, Equinox, Spring DM。因为都是基于OSGi标准的,他们的大致用法和核心功能是一致的。一般来说一个OSGi的组件(Bundle)可以轻易的从一个框架迁移到另一个框架。框架的不同主要是体现在他们本身的设计和额外的服务上。根据我的一些经验,对这4个框架进行了一下比较,希望对刚接触OSGi或是由于如何选择OSGi框架的人有所帮助。

3、区别

SpringDM并不是OSGi的标准实现,它的运行必须依赖OSGi的标准容器,比如Equinox、Felix或是Knopflerfish等。SpringDM只是帮助我们用一种我们所熟悉的编程方式来完成OSGi服务的注册、查询、使用和监听。我们也可以将这些OSGi服务称之为Bean。所以SpringDM依赖于OSGi容器,没有OSGi容器,则SpringDM就无法运行,相反的,如果没有SpringDM,则OSGi服务将变的非常的难以使用,不利于OSGi技术的推广和发展。

1)应用程序上下文

在Spring中最核心的概念就是应用程序上下文(Application Context),在应用程序上下文中则包含了一些Bean定义。应用程序上下文可以被配置成具有层次关系,这样一个子应用程序上下文可以使用其父应用程序上下文中定义的Bean,反之却不行,这种层次关系与classloader之间的层次关系非常的相似。Spring中的输出器Bean和工厂Bean则用于将Bean的引用输出到应用程序上下文之外的客户端中,并且将服务的引用注入到客户端中。

2)引用

在OSGi bundle和Spring应用程序上下文之间有很自然的紧密联系。使用Spring Dynamic Modules,一个处于Active状态的Bundle可以包含一个Spring 应用程序上下文,它负责在Bundle中实例化、配置、组装和装饰Bean。这些Bean即可作为OSGi服务输出并提供给其他Bundle引入,也可以注入其他OSGi服务输出的Bean引用。

3)功能

Spring DM提供了一个OSGi bundle:org.springframework.osgi.bundles.extender(在Gemini Blueprint中不再是这个包名),这个Bundle负责为应用程序Bundle实例化Spring应用程序上下文。它的功能和用于Spring Web应用程序的ContextLoaderListener一样。一旦Extender Bundle被安装和启动,它就会寻找所有基于Spring的且已经在ACTIVE状态的Bundle,并且替它们创建应用程序上下文。另外Extender Bundle还监听Bundle启动事件和为所有后启动的基于Spring 的Bundle创建应用程序上下文。Extender Bundle异步地创建应用程序上下文。这样使得OSGi 服务平台能快速地启动,而且不会导致具有内部依赖性服务的Bundle在启动时死锁。一旦Bundle的应用程序上下文创建成功,应用程序上下文对象会自动通过OSGi服务注册表输出为可用服务。

上下文发布为org.springframework.context.ApplicationContext接口。被发布的服务有一个名为org.springframework.context.service.name的服务属性,该属性值为Bundle在应用程序上下文里注册的标记名称。把应用程序上下文发布为服务主要用于方便测试和管理。在运行时通过getBean或类似操作来获取上下文对象并不被鼓励使用。获取在其他应用程序上下文里定义的Bean的最好方式是将该Bean在它的定义上下文里输出为OSGi服务,然后在要用到服务的上下文里导入该服务。通过这种方式使用服务注册表确保Bean仅能获取和所需服务类型兼容的服务,而且OSGi平台的动态性也得到了尊重。