`
nanjingjiangbiao_T
  • 浏览: 2585341 次
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

Spring-OSGI 1.0 M3 中文手册

 
阅读更多

Spring Dynamic Modules Reference Guide

for OSGi(tm) Service Platforms.

Version 1.0 M3

1.0 Introduction

This document is the reference guide for Spring Dynamic Modules. It defines the syntax and semantics for the OSGi Service Platform based namespaces; the Dynamic Modules extender bundle; and the OSGi manifest header entries defined by Dynamic Modules. For a tutorial introduction to building OSGi-based applications with Spring Dynamic Modules see the online tutorials and user guide.

OSGi developers looking for an introduction to Spring should review the introductory articles on the springframework.org site.

Note: OSGi is a trademark of the OSGi Alliance. Project name is pending final approval from the Alliance.

Note: Please see the known issues page for Spring Dynamic Modules 1.0 M3 release.

由于商标关系,Spring-osgi改名为 Spring Dynamic Modules

这个文档是Spring Dynamic Modules的手册。它定义了基于名字空间的OSGI服务平台的语法和语义,动态模块bundle和由动态模块定义的OSGI manifest header entries。通过在线指南和用户指南可以了解到使用Spring Dynamic Modules构造基于OSGI的应用

Why Spring Dynamic Modules?

The Spring Framework is the leading full-stack Java/JEE application framework. It provides a lightweight container and a non-invasive programming model enabled by the use of dependency injection, AOP, and portable service abstractions. The OSGi Service Platform offers a dynamic application execution environment in which modules (bundles) can be installed, updated, or removed on the fly. It also has excellent support for modularity and versioning.

Spring是一个全功能的Java/JEE应用框架。它提供了一个轻量级的容易和一个用于依赖注入的非侵入式编程模块,AOP功能和便携式服务抽取。OSGI服务平台提供了一个动态应用执行环境,模块能随时被加载,更新或卸载。当然它对模块和版本控制有很好的支持。

Spring Dynamic Modules makes it easy to write Spring applications that can be deployed in an OSGi execution environment, and that can take advantage of the services offered by the OSGi framework. Spring's OSGi support also makes development of OSGi applications simpler and more productive by building on the ease-of-use and power of the Spring Framework. For enterprise applications, the combination of Spring Dynamic Modules and the OSGi platform provides:

  • Better separation of application logic into modules, with runtime enforcement of module boundaries
  • The ability to deploy multiple versions of a module (or library) concurrently
  • The ability to dynamically discover and use services provided by other modules in the system
  • The ability to dynamically install, update and uninstall modules in a running system
  • Use of the Spring Framework to instantiate, configure, assemble, and decorate components within and across modules.
  • A simple and familiar programming model for enterprise developers to exploit the features of the OSGi platform.

We believe that the combination of OSGi and Spring offers a comprehensive model for building enterprise applications.\

Spring Dynamic Modules使编写一个部署在OSGI执行环境中的Spring应用变得简单,它能利用OSGI框架提供的服务。Spring的osgi支持也使构建在Spring框架中的OSGI应用开发变得更简单,更高产。对于企业级应用,Spring动态模块与OSGI平台的整合能提供以下功能:

  • 模块内部更好的应用逻辑分离
  • 同时部署同一模块的多个版本
  • 在系统中动态发现和使用模块提供的服务
  • 在系统运行时动态安装,更新和卸载模块
  • 使用Spring框架初始化,配置,整合并使用模块中和跨模块的组件
  • 对于使用OSGI平台特性的企业级开发者来说这些都是简单和熟悉的编程模型

Supported OSGi and JDK versions

Spring Dynamic Modules supports OSGi R4 and above, and JDK level 1.4 and above. Bundles deployed for use with Spring Dynamic Modules should specify "Bundle-ManifestVersion: 2" in their manifest. We test against Equinox, Felix, and Knopflerfish as part of our continuous integration process.

要使用Spring动态模块应该在MANIFEST.MF中指定 Bundle-ManifestVersion: 2

Structure of this document

Chapter 2, "Bundles and Application Contexts" describes the relationship between an OSGi Bundle and a Spring Application Context, and introduces the Spring Extender Bundle support for instantiating application contexts automatically.

第二章,"Bundles and Application Contexts"描述了OSGI Bundle与Spring Application Context 的关系,并且介绍了Spring Extender Bundle支持自动初始化应用上下文Application Contexts

Chapter 3, "Packaging and Deploying Spring-based OSGi applications" describes how to deploy the Spring Framework jar files in an OSGi environment, and how to reference external APIs from your application bundles should you need to do so. This chapter also explains some of the issues to be aware of when using existing enterprise libraries not designed for OSGi in an OSGi environment.

第三章,"Packaging and Deploying Spring-based OSGi applications" 描述了如何将Spring框架的jar文件部署到OSGI环境中,并且如何在你的应用bundles中引用外部APIs。本章还解释了在OSGI环境中当使用一些并不是为OSGI而设计的已经存在的企业类库时出现的问题

Chapter 4, "The Service Registry" describes how to export Spring beans as services in the OSGi service registry, and how to inject references to OSGi services into beans. This chapter also defines how the dynamic life-cycle of OSGi services and bundles is supported.

第四章,"The Service Registry" 描述了如何在OSGi service registry中将Spring beans做为服务输出,如何将OSGI服务引用注入到bean里。本章还定义了如何动态支持OSGI服务和Bundles的生命周期

Chapter 5, "Working with Bundles" describes how to declare a bean that represents an OSGi bundle, including support for installing new bundles into the OSGi platform.

第五章,"Working with Bundles" 描述了如何声明一个bean,表现为一个OSGI bundle,包括对安装一个新bundle到OSGI平台中的支持。

Chapter 6, "Compendium Services" describes the support provided for the OSGi Compendium Services, including the Configuration Admin service.

第六章,"Compendium Services" 描述了OSGi Compendium Services提供的支持,包括Configuration Admin service

Chapter 7, "Testing OSGi based Applications" explains the integration testing support provided by Spring Dynamic Modules. This support enables you to write simple JUnit integration tests that can start up an OSGi environment, install the bundles needed for the integration test, execute the test case(s) inside of OSGi, and return the results to the runner. This support makes it easy to integrate OSGi integration testing into any environment that can work with JUnit.

第七章,"Testing OSGi based Applications" 介绍了Spring动态模块提供的综合测试支持。这个功能使你能写一些简单的JUnit综合测试,这个功能能启动OSGI环境,安装测试所需的bundles,执行OSGI里的测试案例,并且返回结果。这个功能使 将OSGI综合测试整合进任何JUnit环境 变得简单。

Appendix A, "Extensions" describes extensions that are included in the 1.0 distribution, but are not guaranteed to be maintained in a backward-compatible form in future point releases. We anticipate these features moving into the core specification over time.

Appendix B, "Roadmap" describes some features that are included in the 1.0 distribution but are still considered early-access. The externals of these features may change in future releases. This appendix also discusses other planned features for which no implementation yet exists.

Appendix C defines the schemas provided by Spring Dynamic Modules.

2.0 Bundles and Application Contexts

The unit of deployment (and modularity) in OSGi is the bundle (see section 3.2 of the OSGi Service Platform Core Specification). A bundle known to the OSGi runtime is in one of three steady states: installed, resolved, or active. Bundles may export services (objects) to the OSGi service registry, and by so doing make these services available for other bundles to discover and to use. Bundles may also export Java packages, enabling other bundles to import the exported types.

OSGI中的一个部署(或模块)单元称为bundle。一个OSGI运行环境中的bundle有3个固定的状态:installed,resolved, active。这些bundle能做为服务输出到OSGi service registry,这样这些服务就能被其他bundle发现和使用。bundle也可以输出为java包,使其他bundle能够引用这些被输出的类型。

In Spring the primary unit of modularity is an application context, which contains some number of beans (objects managed by the Spring application context). Application contexts can be configured in a hierarchy such that a child application context can see beans defined in a parent, but not vice-versa. The Spring concepts of exporters and factory beans are used to export references to beans to clients outside of the application context, and to inject references to services that are defined outside of the application context.

Spring中最主要的模块单元是application context,它包含了一定数量的bean(由spring application context管理)。Application contexts可以被配置成父子层次,例如child application 能找到parent application 中定义的bean,反之则不行。Spring中的exporters和factory beans的是将bean引用输出到application context以外的客户端,并且将这些引用注入客户端定义的服务中。

There is a natural affinity between an OSGi bundle and a Spring application context. Using Spring Dynamic Modules, an active bundle may contain a Spring application context, responsible for the instantiation, configuration, assembly, and decoration of the objects (beans) within the bundle. Some of these beans may optionally be exported as OSGi services and thus made available to other bundles, beans within the bundle may also be transparently injected with references to OSGi services.

OSGi bundle和Spring application context是天生的一对(natural affinity)。如果使用了Spring Dynamic Modules(Spring-osgi),那么一个状态为active的bundle也许包含一个spring application context,它负责bundle中的bean的初始化,配置,整合和装载。

2.1 The Spring Dynamic Modules Extender bundle

Spring Dynamic Modules provides an OSGi bundle

org.springframework.osgi.spring-osgi-extender

. This bundle is responsible for instantiating the Spring application contexts for your application bundles. It serves the same purpose as the ContextLoaderListener does for Spring web applications. Once the extender bundle is installed and started it looks for any existing Spring-powered bundles that are already in the ACTIVE state and creates application contexts on their behalf. In addition, it listens for bundle starting events and automatically creates an application context for any Spring-powered bundle that is subsequently started. Section 3 describes what the extender recognizes as a "Spring-powered bundle".

Spring Dynamic Modules提供了一个OSGi bundle -

org.springframework.osgi.spring-osgi-extender

。这个bundle负责为你的application bundles初始化一个Spring application contexts。它的功能与Spring web applications中的ContextLoaderListener一样。一旦这个bundle(

org.springframework.osgi.spring-osgi-extender)被安装并且启动,它将查找所有已经存在的具有spring-powered的状态为ACTIVE的bundle,然后为它们创建一个application context。另外,它还监听bundle的启动事件并自动为这个随后启动的bundle创建一个appliation context。第3节描述了什么样的bundle具备Spring-powered。

2.2 Application Context Creation

The extender bundle creates applications contexts asynchronously. This behavior ensures that starting an OSGi Service Platform is fast and that bundles with service inter-dependencies do not cause deadlock on startup. A Spring-powered bundle may therefore transition to the STARTED state before its application context has been created. It is possible to force synchronous creation of application contexts on a bundle-by-bundle basis. See section 3 for information on how to specify this behavior.

Spring的extender bundle (

org.springframework.osgi.spring-osgi-extender

)生成applications contexts是异步过程,不会使bundle间的相互依赖发生死锁而减缓OSGI服务平台的速度,因此一个具有Spring-powered的bundle的状态可能会在extender bundle为它生成生成application context之前就转变成STARTED。也可以强行一个bundle一个bundle的同步创建application contexts,第三节详细介绍了这个过程。

If application context creation fails for any reason then the failure cause is logged. The bundle remains in the STARTED state. There will be no services exported to the registry from the application context in this scenario.

任何一个application context创建失败都会被记录,bundle的状态继续保持为STARTED,并且这个bundle不会有任何服务被注册。

2.2.1 Mandatory Service Dependencies

If an application context declares mandatory dependencies on the availability of certain OSGi services (see section 4.0) then creation of the application context is blocked until all mandatory dependencies can be satisfied through matching services available in the OSGi service registry. Since a service may come and go at any moment in an OSGi environment, this behavior only guarantees that all mandatory services were available at the moment creation of the application context began. One or more services may subsequently become unavailable again during the process of application context creation. Section 4.0 describes what happens when a mandatory service reference becomes unsatisfied. In practice for most enterprise applications built using Spring Dynamic Modules services the set of available services and bundles will reach a steady state once the platform and its installed bundles are all started. In such a world the behavior of waiting for mandatory dependencies simply ensures that bundles A and B, where bundle A depends on services exported by bundle B, may be started in any order.

如果一个application context声明有强制依赖某个有效的OSGI服务,那么这个application context的线程将会暂时阻塞直到所有的强制依赖服务都与OSGi service registry中的服务相匹配。因为一个服务随时可能出现,所以这个阻塞过程仅仅能保证所有的强制依赖在application context生成时可用,而application context创建后某些服务可能会重新变得不可用。第四节描述了当一个强制依赖服务引用不匹配时会发生什么。在大多数用Spring Dynamic Modules构建服务的企业级应用实践中,一旦OSGI平台和它的已安装的bundle被启动后,这些服务和bundle就会达到一个稳定的状态。

A timeout applies to the wait for mandatory dependencies to be satisfied. By default the timeout is set to 5 minutes, but this value can be configured using the

timeout

directive. See section 3.0 for details.

超时用于等待强制依赖关系被解除,默认的超时时间是5分钟,但是可以通过配置修改这个值。具体细节参见3.0节

It is possible to change the application context creation semantics so that application context creation fails if all mandatory services are not immediately available upon startup (see section 3.1). When configured to not wait for dependencies, a bundle with unsatisfied mandatory dependencies will be stopped, leaving the bundle in the RESOLVED state.

如果系统启动时所有的依赖服务不能马上可用,可以修改application context的创建逻辑使application context创建失败。当带有强制依赖的bundle配置成不等待依赖服务时,它将被停止,状态标记为RESOLVED。

2.2.2 Application Context Service Publication

Once the application context creation for a bundle has completed, the application context object is automatically exported as a service available through the OSGi Service Registry. The context is published under the interface

org.springframework.context.ApplicationContext

(and also all of the visible super-interfaces and types implemented by the context). The published service has a service property named

org.springframework.context.service.name

whose value is set to the bundle symbolic name of the bundle hosting the application context. It is possible to prevent publication of the application context as a service using a directive in the bundle's manifest. See section 3.2 for details.

一旦bundle的application context创建完成,application context对象将通过OSGi Service Registry注册为服务,发布类型为

org.springframework.context.ApplicationContext,它会包含一个属性

org.springframework.context.service.name

,值为它的bundle的标记名(symbolic name)。可以通过配置bundle的MANIFEST.MF使application context不做为一个服务发布。

Note: the application context is published as a service primarily to facilitate testing, administration, and management. Accessing this context object at runtime and invoking

getBean()

or similar operations is discouraged. The preferred way to access a bean defined in another application context is to export that bean as an OSGi service from the defining context, and then to import a reference to that service in the context that needs access to the service. Going via the service registry in this way ensures that a bean only sees services with compatible versions of service types, and that OSGi platform dynamics are respected.

注意:application context发布为服务主要是为了方便测试,管理和操作。不鼓励运行时访问context对象和通过getBean()之类的方法。要访问一个定义在别的application context中的bean,更好的方法是在那个application context中将bean输出为OSGi服务,然后在需要访问这个服务的application context中引入服务的引用,通过服务注册,可以确保一个bean只能看见与之版本兼容的服务类型,这也是OSGi动态平台所注重的地方。

2.3 Bundle Lifecycle

OSGi is a dynamic platform: bundles may be installed, started, updated, stopped, and uninstalled at any time during the running of the framework.

OSGi是一个动态平台:运行中的OSGi框架可以在任何时候安装,启动,更新,停止和卸载bundle。

When an active bundle is stopped, any services it exported during its lifetime are automatically unregistered and the bundle returns to the resolved state. A stopped bundle should release any resources it has acquired and terminate any threads. Packages exported by a stopped bundle continue to be available to other bundles.

当一个活动的bundle被停止时,在它处于激活状态时输出的任何服务将自动卸载,并且它的状态会返回到RESOLVED。一个停止活动的bundle应该释放它所有获得的资源并终止所有它开启的线程。但是它输出的packages仍然对其他bundles有效。

A bundle in the resolved state may be uninstalled: packages that were exported by an uninstalled bundle continue to be available to bundles that imported them (but not to newly installed bundles).

一个状态为RESOLVED的bundle可以被卸载:一个被卸载的bundle输出的packages对其他已经存在的bundles仍然有效(但是对新安装的bundles无效)。

A bundle in the resolved state may also be updated. The update process migrates from one version of a bundle to another version of the same bundle.

一个状态为RESOLVED的bundle也可以被更新。这个更新过程是指同一个bundle从一个版本移植到另一个版本。

Finally of course a resolved bundle can be started, which transitions it to the active state.

最后一个状态为RESOLVED的bundle还可以被启动,它的状态则改变为ACTIVE。

The OSGi

PackageAdmin

refreshPackages

operation refreshes packages across the whole OSGi framework or a given subset of installed bundles. During the refresh, an application context in an affected bundle will be stopped and restarted. After a

refreshPackages

operation, packages exported by older versions of updated bundles, or packages exported by uninstalled bundles, are no longer available. Consult the OSGi specifications for full details.

OSGi中的org.osgi.service.packageadmin.PackageAdmin.refreshPackages(Bundle[] bundles)可以刷新整个OSGi框架或指定的一列已安装的bundles中的packages。如果某个bundle被刷新,那么它的application context将会被停止然后刷新。

refreshPackages方法执行完毕后,被更新的旧版本的或被卸载了的bundle的packages将不再有效。具体细节参见OSGi规范。

When a Spring-powered bundle is stopped, the application context created for it is automatically destroyed. All services exported by the bundle will be unregistered (removed from the service registry) and the normal application context tear-down life-cycle is observed (

DisposableBean

and

destroy-method

callbacks are invoked on beans in the context).

当一个具有Spring-powered的bundle被停止时,它的application context将自动销毁,它输出的服务将被注销(从service registry删除),然后application context生命周期的正常注销将开始执行(回调context中所有bean的

destroy-method

If a Spring-powered bundle that has been stopped is subsequently re-started, a new application context will be created for it.

如果一个已经停止的具有Spring-powered的bundle后来又重新启动,那么一个新的application context将会被创建。

2.4 The Resource abstraction

The Spring Framework defines a resource abstraction for loading resources within an application context (see Spring's resource abstraction). All resource loading is done through the

ResourceLoader

associated with the application context. The

ResourceLoader

is also available to beans wishing to load resources programmatically. Resource paths with explicit prefixes - for example "classpath:" are treated uniformly across all application context types (for example, web application contexts and classpath-based application contexts). Relative resource paths are interpreted differently based on the kind of application context being created. This enables easy integration testing outside of the ultimate deployment environment.

Spring框架为从application context中加载资源定义了一个资源提取功能。通过与application context相关联的

ResourceLoader可以完成资源加载。

ResourceLoader也适用于bean在程序中加载资源。资源路径会有很清楚的前缀 - 例如“classpath:”前缀将一律被看成是跨application context级的类型(例如web application contexts和基于classpath的application contexts)。其他相关的资源路径则根据application context的创建方式不同而不同,这使得最终部署环境的外部综合测试变得简单。

The Spring extender bundles creates a special subclass of application context, an

OSGiApplicationContext

. An OSGi application context treats a relative resource path as a reference to a resource defined within the bundle (the bundle and its attached fragments will be searched for matching resources). The context also supports the explicit resource path prefixes

osgibundle

and

osgibundlejar

.

The Spring extender bundles会创建一个特殊的application context的子application context -

OSGiApplicationContext(只适用于OSGi环境的application context)。一个OSGi application context将相关的资源路径看成定义在bundle中的资源引用(在bundle和它的附加文件中查找匹配的资源)。这个OSGi application context也支持前缀为 "

osgibundle:"

和 "

osgibundlejar:"

的资源路径。

A resource path of the format "osgibundle:x/y/z" searches for resource "x/y/z" in the bundle and its attached fragments (this is the same as the relative resource behavior).

一个格式为"osgibundle:x/y/z"的资源路径表示在bundle和它的附加文件中查找资源"x/y/z"(这与其它的查找方式是相似的)。

A resource path of the format "osgibundlejar:x/y/z" searches for resource "x/y/z" in the bundle only, ignoring any attached fragments.

一个格式为"osgibundlejar:x/y/z"的资源路径表示仅仅在bundle中查找资源"x/y/z",不在附加文件中查找。

A resource path using the "classpath:" prefix searches the bundle classpath for matching resources.

一个使用前缀为"classpath:"的资源路径则在bundle的classpath中查找匹配的资源。

All of the regular Spring resource prefixes such as "file:" and "http:" are also supported, as are the pattern matching wildcards. Resources loaded using such prefixes may come from any location, they are not restricted to being defined within the resource-loading bundle or its attached fragments.

类似"file:"和 "http:",Spring中列出的资源路径前缀和通配符匹配模式也是被支持的,使用这些前缀加载的资源可能会来自任何位置,这些资源在bundle或bundle的附加片段中的定义是不被限制的。

OSGi platforms may define their own unique prefixes for accessing bundle contents. For example, Equinox defines the 'bundleresource:' and 'bundlentry:' prefixes). These platform specific prefixes may also be used with Spring OSGi, at the cost of course of tying yourself to a particular OSGi implementation.

OSGi平台可能会定义它自己的唯一前缀去访问bundle。例如,Equinox定义了'bundleresource:'和'bundlentry:'。这些平台所特有的前缀也可能会被Spring OSGi使用,这取决于你使用的是什么OSGi实现框架(Equinox,Felix等)。

2.5 Accessing the BundleContext

In general there is no need to depend on any OSGi APIs when using the Spring Dynamic Modules support. If you do need access to the OSGi

BundleContext

object for your bundle, then Spring makes this easy to do.

通常情况下,在使用Spring Dynamic Modules时是不需要使用任何OSGi APIs的,如果你需要在你的bundle中使用OSGi

的BundleContext对象,那么Spring可以很轻松的做到这一点。

The OSGi application context created by the Spring extender will automatically contain a bean of type

BundleContext

and with name

bundleContext

. You can inject a reference to this bean into any bean in the application context either by-name or by-type. In addition, Spring Dynamic Modules defines the interface

org.springframework.osgi.context.BundleContextAware

:

如果一个bundle具有Spring-powered,由Spring extender为其创建的OSGi application context将自动包含一个类型为org.osgi.framework.

BundleContext的bean,变量名为

bundleContext

。你可以通过bean名字或类型将这个bean注入到application context中的任何一个bean中。另外Spring Dynamic Modules还定义了这样一个接口:

public interface BundleContextAware {

public void setBundleContext(BundleContext context);

}

Any bean implementing this interface will be injected with a reference to the bundle context when it is configured by Spring. If you wish to use this facility within a bundle, remember to import the package

org.springframework.osgi.context

in your bundle manifest.

任何实现了这个接口的bean被Spring初始化时都会被注入一个bundle context。你需要在bundle的manifest中引入

org.springframework.osgi.context

才能使用这个功能。

2.5.1 ThreadLocal access to BundleContext

During creation of an application context, access to the

BundleContext

object for the bundle is also available through an inheritable thread-local variable. This variable is accessible via the

org.springframework.osgi.context.support.LocalBundleContext

class.

在一个application context被创建的时候,通过thread-local变量也可以使用

BundleContext对象。这个变量通过类

org.springframework.osgi.context.support.LocalBundleContext

访问。

public class LocalBundleContext {

public static BundleContext getContext();

}

In addition, when an operation is invoked on an OSGi service reference injected by Spring, Spring makes sure that the invoking bundle's

BundleContext

is accessible on the invoking thread via the

LocalBundleContext

.

另外,当一个由Spring注入的OSGi服务被调用的时候,Spring会通过

LocalBundleContext

确保调用的bundle的

BundleContext在调用线程中是可用的。

2.6 Stopping the extender bundle

If the extender bundle is stopped, then all the application contexts created by the extender will be destroyed. Application contexts are shutdown in the following order:

如果spring extender bundle被停止,那么它创建的所有application contexts将被注销。Application contexts的关闭顺序如下:

  1. Application contexts that do not export any services, or that export services that are not currently referenced, are shutdown in reverse order of bundle id. (Most recently installed bundles have their application contexts shutdown first).

    Application contexts没有输出任何服务或输出的服务没有被引用,那么则根据它们内部的bundle ID从大到小的顺序关闭(跟堆栈类似,后生成的application contexts先关闭)。

  2. Shutting down the application contexts in step (1) may have released references these contexts were holding such that there are now additional application contexts that can be shutdown. If so, repeat step 1 again.

    步骤(1)中关闭的application contexts可能已经释放了被它们持有的其他application contexts的引用,于是更多的application contexts就能够被关闭了,如果是这样,则重复步骤一。

  3. If there are no more active application contexts, we have finished. If there are active application contexts then there must be a cyclic dependency of references. The circle is broken by determining the highest ranking service exported by each context: the bundle with the lowest ranking service in this set (or in the event of a tie, the highest service id), is shut down. Repeat from step (1).

    如果没有application contexts处于激活状态,那么就完成了关闭。如果还有处于激活的application contexts,那么一定有被嵌套依赖的引用。解除这个嵌套依赖关系将由各个context输出的最高队列等级的服务决定:通过重复步骤(1)关闭这个嵌套依赖中级别最低的服务的bundl。

3.0 Packaging and Deploying Spring-based OSGi applications

A traditional Spring application uses either a single application context, or a parent context containing service layer, data layer, and domain objects with a child context containing web layer components. The application context may well be formed by aggregating the contents of multiple configuration files.

通常Spring application使用单一的application context或是一个带有包含web层组件的子context的父context,它们包含服务层,数据层和域对象。application context可以又多个配置文件集成的内容组成。

When deploying an application to OSGi the more natural structure is to package the application as a set of peer bundles (application contexts) interacting via the OSGi service registry. Independent subsystems should be packaged as independent bundles or sets of bundles (vertical partitioning). A subsystem may be package in a single bundle, or divided into several bundles partitioned by layer (horizontal partitioning). A straightforward web application may for example be divided into four modules (bundles): a web bundle, service layer bundle, data layer bundle, and domain model bundle. Such an application would look like this:

将一个应用部署到OSGi中更好的结构是将这些应用打包成一系列的bundles,它们通过OSGi service registry 相互作用。独立的子系统应该被打包成一个独立的bundle或划分成多个bundles(垂直划分)或是通过不通的层划分成多个bundles(水平划分)。例如,一个简单的web application可能会被划分成4个模块(4个bundle):页面显示层bundle,服务层bundle,数据层bundle和域模型bundl。Spring-OSGI 1.0 M3 中文手册(1) - haizai219 - dinstone的IT农场

In this example the data layer bundle yields a data layer application context that contains a number of internal components (beans). Two of those beans are made publicly available outside of the application context by publishing them as services in the OSGi service registry.

在这个例子中,数据层bundle生成一个包含了很多内部组件(beans)的数据层application context。在the OSGi service registry中将这些bean中的其中2个bean做为服务发布可以在application context外部使用它们。

The service layer bundle yields a service layer application context that contains a number of internal components (beans). Some of those components depend on data layer services, and import those services from the OSGi service registry. Two of the service layer components are made externally available as services in the OSGi service registry.

服务层bundle生成一个包含了很多内部组件(beans)的服务层application context。它们中的某些组件依赖于从OSGi service registry中引入的数据层的服务。

The web component bundle yields a web application context that contains a number of internal components (beans). Some of those components depend on application services, and import those services from the OSGi service registry. Since the domain model bundle contributes only domain model types, but does not need to create any components of its own, it has no associated application context.

3.1 Bundle format and Manifest headers

Each application module should be packaged as an OSGi bundle. A bundle is essentially a jar file with a

META-INF/MANIFEST.MF

file containing a series of headers recognized by the OSGi Service Platform. See the OSGi Service Platform Core Specification section 3.2 for details. Some OSGi implementations may support exploded jar files, but the format remains the same.

每一个应用模块都应该打包成一个OSGi bundle。一个bundle其实就是一个含有

META-INF/MANIFEST.MF的jar包,

META-INF/MANIFEST.MF

中有一系列经过OSGi服务平台验证的headers。关于headers的细节参见OSGi规范中的3.2节。一些OSGi实现框架可能会支持一些与众不同的jar包,但是这些jar包关于OSGi的格式还是不变的。

The Spring extender recognizes a bundle as "Spring-powered" and will create an associated application context when the bundle is started if one or both of the following conditions is true:

如果满足以下两个条件,Spring extender会通过一个bundle的具有"Spring-powered"的验证,当这个bundle启动时会为其创建一个相关联的application context:

  • The bundle classpath contains a folder

    META-INF/spring

    with one or more files in that folder with a '.xml' extension.

    这个bundle的classpath包含一个目录

    META-INF/spring

    ,这个目录中有一个或多个扩展名为'.xml'的文件。

  • META-INF/MANIFEST.MF

    contains a manifest header

    Spring-Context

    .

    这个bundle中的

    META-INF/MANIFEST.MF

    文件包含一个名为

    Spring-Context

    的header。

In addition, if the optional

SpringExtender-Version

header is declared in the bundle manifest, then the extender will only recognize bundles where the specified version constraints are satisfied by the version of the extender bundle (

Bundle-Version

). The value of the

SpringExtender-Version

header must follow the syntax for a version range as specified in section 3.2.5 of the OSGi Service Platform Core Specification.

另外,如果bundle的manifest声明了可选header -

SpringExtender-Version,那么extender将仅仅认可与之版本相符的指定版本约束的bundle(bundle的

Bundle-Version

)。

SpringExtender-Version

的值必须遵循OSGi规范3.2.5节中指定的版本范围。

In the absence of the

Spring-Context

header the extender expects every ".xml" file in the

META-INF/spring

folder to be a valid Spring configuration file, and all directives (see below) take on their default values.

在缺少

Spring-Context的情况下,spring extender仍然认为所有

META-INF/spring

中".xml"的文件都是spring的配置文件,所有的header都是默认值。

An application context is constructed from this set of files. A suggested practice is to split the application context configuration into at least two files, named by convention modulename-context.xml and modulename-osgi-context.xml. The modulename-context.xml file contains regular bean definitions independent of any knowledge of OSGi. The modulename-osgi-context.xml file contains the bean definitions for importing and exporting OSGi services. It may (but is not required to) use the Spring Dynamic Modules OSGi schema as the top-level namespace instead of the Spring 'beans' namespace.

application context就是根据这些文件(

META-INF/spring

中".xml"的文件)构造的。一个推荐的做法是将application context配置文件至少分割成2个文件,习惯上命名为 [模块名-context.xml] 和[模块名-osgi-context.xml]。modulename-context.xml文件包含了不依赖与OSGi相关的bean的定义(可以理解为普通bean定义)。modulename-osgi-context.xml文件则定义那些引入或输出OSGi服务的bean。这可能需要使用Spring Dynamic Modules的OSGi schema做为顶级命名空间,取代spring的'bean'命名空间,但这不是必须的。

=====================以下是 Spring-Context的相关内容和配置,主要意思如下:

1.如果在

Spring-Context

指定了配置文件,那么extender将忽略

META-INF/spring

中的配置文件,除非明确指定。

2.可以用通配符,例如

Spring-Context: osgi-*;

3.create-asynchronously=false(默认值是true),使用同步方式创建该bundle的application context。有一点需要注意,同步创建application context的过程是在OSGi的事件线程中进行的,它将阻塞这个线程的事件发送,直到完成application context的初始化。如果这个过程中发生了错误,那么将出现一个FrameworkEvent.ERROR,但是bundle的状态仍然还是ACTIVE。

4.wait-for-dependencies和timeout,从字面意思就能看出来了。

5.publish-context:=false(默认值是true),不将application context作为一个服务发布。

The

Spring-Context

manifest header may be used to specify an alternate set of configuration files. The resource paths are treated as relative resource paths and resolve to entries defined in the bundle and the set of attached fragments. When the

Spring-Context

header defines at least one configuration file location, any files in

META-INF/spring

are ignored unless directly referenced from the

Spring-Context

header.

The syntax for the

Spring-Context

header value is:

Spring-Context-Value ::= context ( ',' context ) *context ::= path ( ';' path ) * (';' directive) *

This syntax is consistent with the OSGi Service Platform common header syntax defined in section 3.2.3 of the OSGi Service Platform Core Specification.

For example, the manifest entry:

Spring-Context: config/account-data-context.xml, config/account-security-context.xml

will cause an application context to be instantiated using the configuration found in the files

account-data-context.xml

and

account-security-context.xml

in the bundle jar file.

A number of directives are available for use with the

Spring-Context

header. These directives are:

  • create-asynchronously (false|true): controls whether the application context is created asynchronously (the default), or synchronously.

For example:

Spring-Context: *;create-asynchronously=false

Creates an application context synchronously, using all of the "*.xml" files contained in the

META-INF/spring

folder.

Spring-Context: config/account-data-context.xml;create-asynchrously:=false

Creates an application context synchronously using the

config/account-data-context.xml

configuration file. Care must be taken when specifying synchronous context creation as the application context will be created on the OSGi event thread, blocking further event delivery until the context is fully initialized. If an error occurs during the synchronous creation of the application context then a FrameworkEvent.ERROR event is raised. The bundle will still proceed to the ACTIVE state.

  • wait-for-dependencies (true|false): controls whether or not application context creation should wait for any mandatory service dependencies to be satisfied before proceeding (the default), or proceed immediately without waiting if dependencies are not satisfied upon startup.

For example:

Spring-Context: config/osgi-*.xml;wait-for-dependencies:=false

Creates an application context using all the files matching "osgi-*.xml" in the config directory. Context creation will begin immediately even if dependencies are not satisfied. This essentially means that mandatory service references are treated as though they were optional - clients will be injected with a service object that may not be backed by an actual service in the registry initially. See section 4.2 for more details.

  • timeout (300): the time to wait (in seconds) for mandatory dependencies to be satisfied before giving up and failing application context creation. This setting is ignored if

    wait-for-dependencies:=false

    is specified. The default is 5 minutes (300 seconds).

For example:

Spring-Context: *;timeout:=60

  • publish-context (true|false): controls whether or not the application context object itself should be published in the OSGi service registry. The default is to publish the context.

For example:

Spring-Context: *;publish-context:=false

If there is no Spring-Context manifest entry, or no value is specified for a given directive in that entry, then the directive takes on its default value.

3.2 Required Spring Framework and Spring Dynamic Modules Bundles

The Spring Dynamic Modules project provides an number of bundle artifacts that must be installed in your OSGi platform in order for the Spring extender to function correctly:

Spring Dynamic Modules提供了很多现成的bundle,要使用Spring extender必须将这些bundle安装到OSGi平台中:

  • The extender bundle itself,

    org.springframework.osgi.extender

  • The core implementation bundle for the Spring Dynamic Modules support,

    org.springframework.osgi.core

  • The Spring Dynamic Modules i/o support library bundle, '

    org.springframework.osgi.io

In addition the Spring Framework provides a number of bundles that are required to be installed. As of release 2.5 of the Spring Framework, the Spring jars included in the Spring distribution are valid OSGi bundles and can be installed directly into an OSGi platform. The minimum required set of bundles is:

另外spring还提供了很多它自己的bundle,这些bundle可以直接被安装到OSGi平台中。要使用spring的最低要求需要以下几个bundle:

  • spring-core.jar (bundle symbolic name

    org.springframework.core

    )

  • spring-context.jar (bundle symbolic name

    org.springframework.context

    )

  • spring-beans.jar (bundle symbolic name

    org.springframework.beans

    )

  • spring-aop.jar (bundle symbolic name

    org.springframework.aop

    )

In additional the following supporting library bundles are required. OSGi-ready versions of these libraries are shipped with the Spring Dynamic Modules distribution.

以下几个bundle是spring的依赖bundle,可以在Spring Dynamic Modules的分发包中找到它们:

  • aopalliance
  • backport-util (for JDK 1.4)
  • cglib-nodep
  • commons-logging (SLF4J version highly recommended)

3.3 Importing and Exporting packages

Refer to the OSGi Service Platform for details of the

Import-Package

and

Export-Package

manifest headers. Your bundle will need an

Import-Package

entry for every external package that the bundle depends on. If your bundle provides types that other bundles need access to, you will need

Export-Package

entries for every package that should be available from outside of the bundle.

这部份是关于OSGi平台MANIFEST中

Import-Package

Export-Package

的细节描述。你的bundle中的MANIFEST.MF需要一个

Import-Package来引入它所依赖的外部package。如果你的bundle提供的type需要被其他bundle使用,你需要使用

Export-Package

将每一个对外部bundle可用的package输出。

3.4 Considerations when using external libraries

Many enterprise application libraries assume that all of the types and resources that comprise the application are accessible through the context class loader. In OSGi R4, the set of types and resources available through the context class loader is undefined. Libraries that generate new classes dynamically can also cause problems in an OSGi environment.

许多企业级应用程序中的libraries(假设这个libraries是组成这个用应用程序的所有types和资源)都能通过context class loader访问和使用,但是在OSGi R4规范中,确不是这样定义的,同样,在OSGi环境中libraries动态生成classes也会产生问题。

Spring Dynamic Modules guarantees that during the creation of an application context on behalf of a given bundle, all of that types and resources on the bundle's classpath are accessible via the context class loader. Spring Dynamic Modules also allows you to control what is accessible through the context class loader when invoking external services and when servicing requests on exported services. See section 4 for details on this.

Spring Dynamic Modules确保了在为bundle生成application context的时候,bundle的classpath下的所有types和资源都可以通过这个application context的classloader去访问和使用。当调用外部服务和响应对输出服务的请求时,Spring Dynamic Modules也允许你控制所有能通过context的classloader访问的资源。具体细节参加第四部份。

Work is underway in the OSGi R5 timeframe to provide standardized support for dealing with generated classes and implicit class path dependencies introduced by third-party libraries. In the interim you may need to rely on workarounds such as the

DynamicImport-Package

manifest header, or the facilities provided by specific OSGi implementations such as Equinox's buddy mechanism. The Spring Dynamic Modules tutorial contains more detail on known issues with common enterprise libraries and the workarounds.

3.5 Diagnosing problems

Your chosen OSGi platform implementation should be able to provide you with a good deal of information about the current status of the OSGi environment. For example, starting Equinox with the

-console

argument provides a command-line console through which you can determine which bundles are installed and their states, the packages and services exported by bundles, find out why a bundle has failed to resolve, and drive bundles through the lifecycle.

OSGi实现框架应该提供很多关于OSGi环境当前状态的信息。例如通过参数-console启动的Equinx会提供一个命令行控制台,通过这个控制台你可以看到哪些bundle被安装了,这些bundle的状态,这些bundle输出的package和服务,找到bundle解析失败的原因,改变bundle生命周期状态。

In addition, Spring itself and the Spring Dynamic Modules bundles contain extensive logging instrumentation that can help you diagnose problems. The recommended approach is to deploy the Simple Logging Facade for Java (slf4j) slf4j-api.jar and slf4j-log4j13.jar bundles (the jar files distributed by the project are valid OSGi bundles). Then you simply need to create a

log4j.properties

file in the root of your bundle classpath.

另外,spring本身和Spring Dynamic Modules bundles包含了logging的扩展包,能帮助你找到问题。推荐的做法是将Simple Logging Facade for Java (slf4j)的slf4j-api.jar和slf4j-log4j13.jar部署成bundle(分发包中的jar包已经是可用的OSGi bundle了),然后你只需要简单的将

log4j.properties放到bundle classpath的根目录下。

4.0 The Service Registry

The OSGi service registry enables a bundle to publish objects to a shared registry, advertised via a given set of Java interfaces. Published services also have service properties associated with them in the registry.

OSGi服务注册器(The OSGi service registry )允许一个bundle将对象发布到一个共享的注册器中,通过一系列java 接口发布注册通知,同时也会有一些服务属性伴随着已经发布的服务。

Spring Dynamic Modules provides an 'osgi' namespace for Spring (see Appendix B) that can be used to export Spring beans as OSGi services, and to define references to services obtained via the service registry. The namespace elements may be used nested inside another top-level namespace (typically the Spring 'beans' namespace), or within the top-level

osgi

element.

Spring Dynamic Modules提供了一个叫'osgi'的命名空间(见附录B),它可以用来将spring bean做为OSGi服务输出,也可以用来定义从service registry中获得的服务的引用。这个命名空间节点可以被嵌套在其他的顶级命名空间中(特别是Spring的'bean'名字空间),或是在顶级命名空间为'osgi'的节点中。

The following example shows the use of the

osgi

namespace within the familiar Spring beans element:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:osgi="http://www.springframework.org/schema/osgi"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://www.springframework.org/schema/osgi

http://www.springframework.org/schema/osgi/spring-osgi.xsd">

<!-- use the OSGi namespace elements qualified with 'osgi:' -->

<osgi:service id="simpleServiceOsgi" ref="simpleService"

interface="org.xyz.MyService" />

</beans>

Using the OSGi namespace as a top-level namespace the same service would be declared as follows:

<?xml version="1.0" encoding="UTF-8"?><osgi xmlns="http://www.springframework.org/schema/osgi"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/osgihttp://www.springframework.org/schema/osgi/spring-osgi.xsd"><!-- use the OSGi namespace elements directly --><service id="simpleServiceOsgi" ref="simpleService"interface="org.xyz.MyService" /></osgi>

Using the OSGi namespace as a top-level namespace is particularly convenient when following the recommendation of section 3.1 to use a dedicated configuration file for all OSGi-related declarations.

使用OSGi名字空间做为顶级名字空间是推荐做法。

4.1 Exporting a Spring bean as an OSGi service

The

service

element is used to define a bean representing an exported OSGi service. At a minimum you must specify the bean to be exported, and the service interface that the service offers.

For example, the declaration

<service>节点用来定义将一个bean描述成一个被输出的OSGi服务,而这至少需要你指定这个要被输出为服务的bean,

和服务的接口类型,例如这个声明:

<service ref="beanToPublish" interface="com.xyz.MessageService"/>

exports the bean with name

beanToPublish

with interface

com.xyz.MessageService

. The published service will have a service property with the name

org.springframework.osgi.beanname

set to the name of the target bean being registered (

beanToPublish

in this case).

这个声明将一个名字为'beanToPublish'输出为接口类型为

com.xyz.MessageService的服务,这个服务将会有一个名字为

org.springframework.osgi.beanname

的service属性,它的值将被设置为bean的名字(在本例中为 beanToPublish)。

The bean defined by the

service

element is of type

org.osgi.framework.ServiceRegistration

and is the

ServiceRegistration

object resulting from registering the exported bean with the OSGi service registry. By giving this bean an id you can inject a reference to the

ServiceRegistration

object into other beans if needed. For example:

由<service>节点定义的bean的类型是

org.osgi.framework.ServiceRegistration,是通过将bean输出的服务注册到the OSGi service registry中形成的ServiceRegistration对象。通过设置一个ID属性可以将这个对象的引用注入到任何一个bean中,例如:

<service id="myServiceRegistration" ref="beanToPublish"

interface="com.xyz.MessageService"/>

As an alternative to exporting a named bean, the bean to be exported to the service registry may be defined as an anonymous inner bean of the service element. Typically the top-level namespace would be the

beans

namespace when using this style:

做为可选择的bean定义,一个输出到service registry中的bean还可以被定义为一个<service>节点的匿名内部bean。使用下面这种风格的定义是使用<beans>做为顶级名字空间的典型代表。

<osgi:service interface="com.xyz.MessageService">

<bean class="SomeClass">

...

</bean>

</osgi:service>

If the bean to be exported implements the

org.osgi.framework.ServiceFactory

interface then the

ServiceFactory

contract is honored as per section 5.6 of the OSGi Service Platform Core Specification. As an alternative to implementing this OSGi API, Spring Dynamic Modules introduces a new bean scope, the

bundle

scope. When a bean with bundle scope is exported as an OSGi service then one instance of the bean will be created for each unique client (service importing) bundle that obtains a reference to it through the OSGi service registry. When a service importing bundle is stopped, the bean instance associated with it is disposed. To declare a bean with

bundle

scope simply use the

scope

attribute of the

bean

element:

按照OSGi服务平台核心规范,如果一个被输出的bean实现了接口org.osgi.framework.ServiceFactory,那么这个ServiceFactory对象与bundle间将会产生一个很受重视的关系。Spring Dynamic Modules引入了一个新的bean范围 - bundle范围。当一个具有bundle范围的bean做为OSGi服务输出的时候,这个bean的一个实例对象将被生成,每一个不同的客户端bundle(引用这个服务的bundle)都通过OSGi service registry获取它。当其中一个引用这个服务的bundle停止时,它所获取的这个bean的实例对象将被除去。要声一个bundle范围的bean,只需要添加一个'scope'属性元素就可以了:

<osgi:service ref="beanToBeExported" interface="com.xyz.MessageService"/>

<bean id="beanToBeExported" scope="bundle" class="com.xyz.MessageServiceImpl"/>

4.1.1 Controlling the set of advertised service interfaces for an exported service

The OSGi Service Platform Core Specification defines the term service interface to represent the specification of a service's public methods. Typically this will be a Java interface, but the specification also supports registering service objects under a class name, so the phrase service interface can be interpreted as referring to either an interface or a class.

OSGi服务平台核心规范定义了术语"service interface"用于描述一个服务的公共方法。具有代表性的就是Java interface,不过OSGi规范也支持通过类名来注册服务对象,所以短语"service interface"也能被理解成接口或类。

There are several options for specifying the service interface(s) under which the exported service is registered. The simplest mechanism, shown above, is to use the

interface

attribute to specify a fully-qualified interface name. To register a service under multiple interfaces the nested

interfaces

element can be used in place of the

interface

attribute.

这里也有一些选项用于注册指定这个被输出的服务实现了的接口。如下面所显示的,最简单的办法是使用interface属性指定一个全路径的接口名。如果要注册一个实现了多接口的服务,可以使用interfaces 节点代替interface属性。

<osgi:service ref="beanToBeExported">

<osgi:interfaces>

<value>com.xyz.MessageService</value>

<value>com.xyz.MarkerInterface</value>

</osgi:interfaces>

</osgi:service>

Using the

auto-export

attribute you can avoid the need to explicitly declare the service interfaces at all. The

auto-export

attribute can have one of four values:

使用'auto-export'属性,可以不用声明一个服务接口,'auto-export'属性具有如下4个值中的其中一个:

  • disabled : the default value; no auto-detected of service interfaces is undertaken and the

    interface

    attribute or

    interfaces

    element must be used instead.

    disabled: 默认值,具有自动检测功能的服务接口将不被启动,必须使用interface属性或interfaces节点。

  • interfaces : the service will be registered using all of the Java interface types implemented by the bean to be exported

    interfaces: 所有被输出的bean所实现的所有java接口将自动被注册。

  • class-hierarchy : the service will be registered using the exported bean's implementation type and super-types

    class-hierarchy: 这个bean的类和它的父类将被自动注册。

  • all : the service will be registered using the exported bean's implementation type and super-types plus all interfaces implemented by the bean.

    all: 包含 interfaces和class-hierarchy

For example, to automatically register a bean under all of the interfaces that it supports you would declare:

<service ref="beanToBeExported" auto-export="interfaces"/>

Given the interface hierarchy:

public interface SuperInterface {}public interface SubInterface extends SuperInterface {}

then a service registered as supporting the

SubInterface

interface is not considered a match in OSGi when a lookup is done for services supporting the

SuperInterface

interface. For this reason it is a best practice to export all interfaces supported by the service being registered explicitly, using either the

interfaces

element or

auto-export="interfaces"

.

在OSGi中,当一个SuperInterface的匹配查找结束时,一个支持SubInterface 的注册的服务是不匹配的。这对于使用使用interfaces 节点或auto-export="interfaces"输出被明确注册的服务所支持的接口是很好的实践。

Note that when using auto-export, only types visible to the bundle exporting the service are registered. For example, a super-interface

SI

would not be exported as a supported service interface even when using

auto-export="interfaces"

if

SI

was not on the exporting bundle's classpath.

注意,当使用auto-export时,仅仅只有对输出服务的bundle可见的types(接口或类)才会被注册。例如,一个super-interface

SI,如果它不在输出bundle的classpath中,

即使当使用auto-export="interfaces",它也不会做为一个被服务支持的接口输出。

4.1.2 Controlling the set of advertised properties for an exported service

As previously described, an exported service is always registered with the service property

org.springframework.osgi.beanname

set to the name of the bean being exported. Additional service properties can be specified using the nested

service-properties

element. The

service-properties

element contains key-value pairs to be included in the advertised properties of the service. The key must be a string value, and the value must be a type recognized by OSGi Filters. See section 5.5 of the OSGi Service Platform Core Specification for details of how property values are matched against filter expressions.

前面已经描述过,一个输出的服务被注册后,会有一个服务属性org.springframework.osgi.beanname,值就是被输出的bean的名字。可以使用嵌套节点service-properties指定一些附加属性,service-properties节点有包含在服务的通知属性中的键-值对。key必须是一个string,value必须是一个经过OSGi Filters验证的type。对于匹配OSGi filters表达式的细节可以参照OSGi规范5.5节。

The

service-properties

element must contain at least one nested

entry

element from the Spring beans namespace.

service-properties节点必须包含至少一个Spring beans名字空间的entry 节点。

For example:

<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface"> <service-properties> <beans:entry key="myOtherKey" value="aStringValue"/> <beans:entry key="aThirdKey" value-ref="beanToExposeAsProperty"/> <service-properties></service>

The Spring Dynamic Modules roadmap includes support for exporting properties registered in the OSGi Configuration Administration service as properties of the registered service. See Appendix A for more details.

Spring Dynamic Modules roadmap 包含了支持将属性做为一个被注册了的服务的属性注册到OSGi Configuration Administration service 中。

4.1.3 The depends-on attribute

Spring will manage explicit dependencies of a service element, ensuring for example that the bean to be exported as a service is fully constructed and configured before exporting it. If a service has implicit dependencies on other components (including other service elements) that must be fully initialized before the service can be exported, then the optional

depends-on

attribute can be used to express these dependencies.

Spring会管理服务元素中明示性的依赖关系,例如确保哪些被做为服务输出的bean在输出之前被完全构造和配置。如果一个服务隐含依赖于其他组件(包括其他服务元素),这个组件在服务被输出之前要被完全初始化,那么可选的属性depends-on能用来表示这种依赖关系。

<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface"

depends-on="myOtherComponent"/>

4.1.4 The ranking attribute

When registering a service with the service registry, you may optionally specify a service ranking (see section 5.2.5 of the OSGi Service Platform Core Specification). When a bundle looks up a service in the service registry, given two or more matching services the one with the highest ranking will be returned. The default ranking value is zero. To explicitly specify a ranking value for the registered service, use the optional

ranking

attribute.

当注册一个服务时,你可能会随意指定一个ranking(关于ranking,参见OSGi规范5.2.5节)。当一个bundle查找一个服务时,ranking最高的与之匹配的服务将会被返回。默认的ranking值是0.使用可选的ranking属性可以为注册的服务指定一个ranking值。

<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface"

ranking="9"/>

4.1.5 The context-classloader attribute

The OSGi Service Platform Core Specification (most current version is 4.1 at time of writing) does not specify what types and resources are visible through the context class loader when an operation is invoked on a service obtained via the service registry. Since some services may use libraries that make certain assumptions about the context class loader, Spring Dynamic Modules enables you to explicitly control the context class loader during service execution. This is achieved using the option

context-classloader

attribute of the service element.

OSGi规范没有指定当通过service registry获取服务的方法被调用时,什么样的types和资源对context class loader可见。所以假设某个服务如果要用到context class loader相关的libraries时,Spring Dynamic Modules允许你在服务执行期明确的控制context class loader,通过service元素的可选属性'context-classloader'来完成。

The permissible values for the

context-classloader

attribute are

unmanaged

(the default) and

service-provider

. When the

service-provider

value is specified, Spring Dynamic Modules ensures that the context class loader can see all of the resources on the class path of the bundle defining the service.

'context-classloader'属性允许的值只有2个 'unmanaged'(默认) 和 'service-provider',当指定'service-provider'值时,Spring Dynamic Modules确保了context class loader 能看见定义这个服务的bundle的classpath中所有的资源。

4.1.6 Service registration and unregistration lifecycle

The service defined by a

service

element is registered with the OSGi service registry when the application context is first created. It will be unregistered automatically when the bundle is stopped and the application context is disposed.

当application context第一次被创建时,由<service>元素定义的服务通过OSGi service registry 注册。这个服务将会在bundle停止和application context被注销时自动注销。

An exported service may depend, either directly or indirectly, on other services in order to perform its function. If one of these services is considered a mandatory dependency (see section 4.2) and the dependency can no longer be satisfied (because the backing service has gone away and there is no suitable replacement available) then the exported service that depends on it will be automatically unregistered from the service registry - meaning that it is no longer available to clients. If the mandatory dependency becomes satisfied once more (by registration of a suitable service), then the exported service will be re-registered in the service registry.

一个输出的服务(ServiceA)可能会因为功能需要而直接或间接地依赖其他服务。如果这些服务中的其中一个服务(ServiceB)匹配ServiceA的强制依赖,并且这个强制依赖关系不再satisfied(因为ServiceB不再可用),那么这个输出的服务(ServiceA)将会自动从service registry中注销,也就是说不再对客户端有效。如果这个强制依赖关系再次变得satified(通过注册一个匹配这个强制依赖关系的服务,可能是ServiceB也可能是其他服务),那么这个输出的服务(ServiceA)将被重新注册到service registry。

This automatic unregistering and re-registering of exported services based on the availability of mandatory dependencies only takes into account declarative dependencies. If exported service

S

depends on bean

A

, which in turn depends on mandatory imported service

M

, and these dependencies are explicit in the Spring configuration file as per the example below, then when

M

becomes unsatisfied

S

will be unregistered. When

M

becomes satisfied again,

S

will be re-registered.

输出服务基于强制依赖的自动注销和重新注册仅仅用在声明性的依赖关系中。在下面给的例子中,输出的服务S依赖bean A,bean A引入了服务M,那么当M变得unsatisfied时,S将会被自动注销,当M重新变得satisfied是,S将重新注册。

<osgi:service id="S" ref="A" interface="SomeInterface"/>

<bean id="A" class="SomeImplementation">

<property name="helperService" ref="M"/>

</bean>

<!-- the reference element is used to refer to a service

in the service registry -->

<osgi:reference id="M" interface="HelperService"

cardinality="1..1"/>

If however the dependency from

A

on

M

is not established through configuration as shown above, but instead at runtime through for example passing a reference to

M

to

A

without any involvement from the Spring container, then Spring Dynamic Modules will not track this dependency.

If you need to take some action when a service is unregistered because its dependencies are not satisfied (or when it is registered), then you can define a listener bean using the nested

registration-listener

element.

如果你想在一个服务因为它的依赖关系不再satisfied(或注册)时做点什么,可以使用嵌套元素registration-listener定义个监听bean

The declaration of a registration listener must use either the

ref

attribute to refer to a top-level bean definition, or declare an anonymous listener bean inline. For example:

声明一个注册监听器必须在顶级bean定义中使用ref 属性或是在它里面声明一个匿名监听器bean。

<!-- example service declaration with two listeners -->

<service ref="beanToBeExported" interface="SomeInterface">

<registration-listener ref="myListener"

registration-method="serviceRegistered"

unregistration-method="serviceUnregistered"/>

<registration-listener

registration-method="register"

unregistration-method="unregister">

<bean class="SomeListenerClass"/>

</registration-listener>

</service>

The optional

registration-method

and

unregistration-method

attributes specify the names of the methods defined on the listener bean that are to be invoked during registration and unregistration. A registration callback method must have a signature matching the following format

可选的registration-method和unregistration-method属性指定了定义在监听bean中的方法的名字,它们会在服务被注册或注销的时候调用。一个注册回调方法必须匹配下面的格式:

public void anyMethodName(ServiceType serviceInstance);

where

ServiceType

can be any type compatible with the exported service interface of the service.

这里的ServiceType 可以是任何type,当然它必须要兼容你要监听的服务的类型

An unregistration callback method must have a signature of the form

public void anyMethodName(ServiceType serviceInstance);

where

ServiceType

can be any type compatible with the exported service interface of the service.

The register callback is invoked when the service is initially registered at startup, and whenever it is subsequently re-registered. The unregister callback is invoked immediately after the service is unregistered, including when the service is unregistered because the bundle is stopping.

注册时回调方法会在系统启动时初次注册服务时调用,也会在服务被重新注册时调用。注销回调方法会在服务被注销后立即调用,包括bundle停止时引起的服务注销。

4.2 Defining references to OSGi services

Spring Dynamic Modules supports the declaration of beans that represent services accessed via the OSGi Service Registry. In this manner references to OSGi services can be injected into application components. The service lookup is made using the service interface type that the service is required to support, plus an optional filter expression that matches against the service properties published in the registry.

Spring Dynamic Modules支持将bean声明为可通过OSGi Service Registry访问的服务,这可以将OSGi services的引用注入到应用组件中。服务的查找是通过使用服务支持的接口类型,再加上可选的匹配发布在registry中的服务属性的过滤器表达式。

For some scenarios, a single matching service that meets the application requirements is all that is needed. The

reference

element defines a reference to a single service that meets the required specification. In other scenarios, especially when using the OSGi whiteboard pattern, references to all available matching services are required. Spring Dynamic Modules supports the management of this set of references as a

List

,

Set

.

在某些情况下,一个与应用需求相应的单一匹配是必须的,<reference>元素定义了一个相应的单一服务的引用。在其他情况下,尤其是当使用OSGi whiteboard pattern时,需要所有可用的匹配服务的应用。Spring Dynamic Modules支持将这些应用做为List或Set去管理。

4.2.1 Referencing an individual service

The

reference

element is used to define a reference to a service in the service registry. The

interface

attribute identifies the service interface that a matching service must implement. For example, the following declaration creates a bean

messageService

, which is backed by the service returned from the service registry when querying it for a service offering the

MessageService

interface.

<reference>元素用来定一个被注册到service registry中的服务的引用。interface 属性用来识别服务接口。例如,下面的声明创建了一个bean - messageService,它实际上是通过查找名字为messageService,接口为MessageService 得到的服务。

<reference id="messageService"

interface="com.xyz.MessageService"/>

If there are several services in the service registry then the service returned is the service that would be returned by a call to

BundleContext.getServiceReference

. This means that the service with the highest ranking will be returned, or if there is a tie in ranking, the service with the lowest service id (the service registered first with the framework) is returned.

如果service registry中有多个服务,那么将通过BundleContext.getServiceReference来返回服务。也就是说返回的这个服务具有最高队列等级,或是如果有一个tie在队列等级中,则返回id最小的那个服务(第一个被注册的服务)。

The bean defined by the reference element implements all of the registered interfaces of the service that are visible to the bundle. If the registered service interfaces include Java class types (as opposed to interface types) then support for these types is subject to the restrictions of Spring's AOP implementation (see the Spring Reference Guide). In short,

cglib

must be available, and

final

methods are not supported.

使用<reference>定义的bean要实现所有注册了的服务接口,这些接口需要对bundle可见。如果注册的服务接口包含了java类(非java接口),那么将会影响到Spring的AOP功能。简单的说,会影响到cglib,并且final方法不被支持。

If the property into which a reference bean is to be injected has type

ServiceReference

(instead of the service interface supported by the reference), then the OSGi

ServiceReference

for the service will be injected in place of the service itself.

如果一个服务的某个属性,被注入的bean的的引用的类型是ServiceReference(它不是被引用所支持的服务接口),那么这个服务的服务引用

将被注入,而不是这个服务本身。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics