osgi容器
OSGi框架(为开发模块化和动态应用程序提供了很好的机制)已经越来越流行。 最新的OSGi服务平台第4版V4.2规范引入了一个称为“蓝图容器”的规范。
蓝图容器规范定义了OSGi的依赖项注入框架。 它旨在处理OSGi的动态性质,在该性质下服务可以随时变得可用和不可用。 该规范还旨在与普通的Java对象(POJO)一起使用,以便可以在OSGi框架内外使用相同的对象。 定义和描述应用程序各种组件的Blueprint XML文件是Blueprint编程模型的关键。 该规范描述了如何实例化组件并将它们连接在一起以形成一个正在运行的应用程序。
蓝图容器规范使用扩展程序模式,扩展程序捆绑包监视框架中捆绑包的状态,并根据其状态代表这些捆绑包执行操作。 蓝图扩展程序束等待束被激活,然后检查它们是否为蓝图束。 当一个捆绑包包含一个或多个Blueprint XML文件时,该捆绑包被视为Blueprint捆绑包。 这些XML文件位于OSGI-INF / blueprint /目录下的固定位置,或在Bundle-Blueprint
清单标头中明确指定。
扩展程序确定捆绑包是Blueprint捆绑包后,便代表该捆绑包创建一个Blueprint容器。 蓝图容器负责:
- 解析蓝图XML文件
- 实例化
- 将组件连接在一起
在初始化期间,蓝图容器确保满足强制性服务引用,将所有服务注册到服务注册表中,并创建初始组件实例。 当捆绑包停止时,Blueprint扩展程序捆绑包还会破坏该捆绑包的Blueprint容器。
本文重点介绍Blueprint XML。 通过几个示例,学习有关组件XML定义及其用法的信息。
蓝图XML
蓝图XML文件由顶级blueprint
元素标识,如清单1所示。
清单1.蓝图XML文件片段
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns=”http://www.osgi.org/xmlns/blueprint/v1.0.0”>
...
</blueprint>
蓝图XML文件包含各种组件管理器的定义。 蓝图容器规范定义了四个主要的组件管理器:一个bean管理器 ,一个服务管理器和两个服务引用管理器 。 每个经理负责创建和管理他们创建的组件的生命周期。 当询问时,管理器提供一个组件实例。 每个管理器都有一个描述该管理器属性的对应XML元素。 经理可以是顶级经理,也可以内联在其他经理定义中。 经理们也有一些共同的属性。
-
id
:定义经理ID。id
属性是可选的。 如果未指定,则将自动生成一个唯一的ID,并将其分配给顶层管理员。 内联管理器被视为匿名管理器,不允许设置id
属性。 蓝图容器中所有顶级管理者的管理者ID必须唯一。 使用这些ID,以便管理者可以相互参考。 例如,在注入期间,管理器将要求引用的管理器提供将被注入到管理器正在创建的组件中的对象。 -
activation
:此可选属性定义管理器的激活模式。 支持两种激活模式:-
eager
,在“蓝图容器”初始化期间激活管理器。 -
lazy
,其中按需激活管理器。
默认情况下,采用
eager
激活模式。 但是,可以通过在blueprint
元素上设置default-activation
属性来更改Blueprint XML文件中所有管理器的默认激活模式。 当要求管理器提供其第一个组件实例时,将激活该管理器。 销毁蓝图容器时,将停用管理器。 每个管理员都有自己的激活和停用步骤。 -
-
dependsOn
:此可选属性指定管理器ID的列表。 在激活管理员之前,将首先激活列出的管理员。 管理器可以具有显式和隐式依赖性。dependsOn
属性定义显式依赖项。 隐式依赖关系是通过在管理器定义中对其他管理器的引用来定义的。
豆经理
Bean管理器使用给定的参数和属性创建Java对象的实例。 Bean管理器可以根据作用域设置创建单个或多个对象实例。 它还可以管理对象的生命周期,并在注入所有属性或销毁对象时通知它。
在Blueprint XML中, bean
元素定义了bean管理器。 用于对象构造的参数由argument
元素指定; 注入的属性由property
子元素指定。
在对象构造期间,蓝图容器必须首先找到正确的构造函数或带有与XML中指定的参数匹配的兼容参数集的工厂方法。 默认情况下,蓝图容器使用XML中argument
元素的数量和顺序来查找正确的构造函数或方法。 如果argument
元素不能按照其顺序映射到参数,则“蓝图容器”将尝试对argument
元素重新排序并找到最合适的安排。
为了帮助“蓝图容器”选择正确的构造函数,方法或参数安排,可以在argument
元素上指定其他属性,例如index
或type
。 例如, type
属性指定一个类名,该类名用于按确切类型将argument
元素与参数匹配。
property
元素指定要注入的属性的名称和值。 该属性名称与Java类中的setter方法名称相对应。 例如,如果属性名称为foo
,则相应的setter方法为setFoo(arg)
。 属性名称和相应的setter方法名称遵循JavaBeans规范中定义的属性设计模式。
argument
和property
元素的value
可以使用value
或ref
属性指定,也可以内联。 ref
属性指定顶级管理器的ID,用于从引用的管理器获取对象作为参数或属性值。 内联值可以是“对象值”部分中描述的任何XML值。
施工
可以通过以下三种方式构造bean:
- 一个类的构造函数
- 静态工厂方法
- 实例工厂方法
清单2、3和4演示了构造Java对象的三种方法。 每个清单都显示了部分Java类以及驱动对象创建的相应Blueprint XML摘录。
清单2显示了一个简单的构造函数创建示例。 在此示例中, class
属性指定要实例化的Java类的名称。 蓝图容器将通过向构造函数传递1
作为参数并调用setDescription()
方法来注入Account
属性,从而创建Account
对象。
清单2.构造器示例
public class Account {
public Account(long number) {
...
}
public void setDescription(String description) {
...
}
public String getDescription() {
...
}
}
<bean id=”accountOne” class=“org.apache.geronimo.osgi.Account”>
<argument value=”1”/>
<property name=”description” value=”#1 account”/>
</bean>
清单3显示了静态工厂方法构造。 在此示例中, class
属性指定包含静态工厂方法的类的名称。 静态工厂方法的名称由factory-method
属性指定。 蓝图容器将在AccountFactory
类上调用createAccount()
静态方法,并传递2
作为创建Account
对象的参数。 一旦工厂返回创建的对象,容器将向其注入description属性。
清单3.静态工厂方法示例
public class StaticAccountFactory {
public static Account createAccount(long number) {
return new Account(number);
}
}
<bean id=”accountTwo” class=“org.apache.geronimo.osgi.StaticAccountFactory”
factory-method=“createAccount”>
<argument value=”2”/>
<property name=”description” value=”#2 account”/>
</bean>
如清单4所示,通过实例工厂方法构造,使用了两个管理器。 一个经理是一个工厂,另一个经理则使用工厂来创建对象。 factory-ref
属性用于指定顶级bean或类似于工厂的引用管理器的ID。 提供的工厂对象必须具有factory-method
属性指定的factory-method
。
在示例中, accountFactory
bean管理器是工厂。 蓝图容器将首先使用其自己的参数和属性创建AccountFactory
实例。 在这种情况下,仅指定一个参数:工厂名称。 然后,蓝图容器将在AccountFactory
实例上调用createAccount()
方法,并传递3
作为参数来创建Account
对象。 一旦工厂返回创建的对象,容器将向其注入description属性。
清单4.实例工厂方法示例
public class AccountFactory {
public AccountFactory(String factoryName) {
...
}
public Account createAccount(long number) {
return new Account(number);
}
}
<bean id=”accountFactory” class=“org.apache.geronimo.osgi.AccountFactory”>
<argument value=”account factory”/>
</bean>
<bean id=”accountThree”
factory-ref=“accountFactory”
factory-method=“createAccount”>
<argument value=”3”/>
<property name=”description” value=”#3 account”/>
</bean>
范围
根据作用域设置,Bean管理器可以创建单个或多个对象实例。 蓝图容器规范定义了两个主要范围:
-
singleton
:bean管理器创建bean的单个实例,并在每次要求管理器提供一个对象时返回该实例。 -
prototype
:每次要求管理器提供一个对象时,bean管理器都会创建一个新的bean实例。
缺省情况下,顶级bean管理器采用singleton
作用域。 不能在嵌入式Bean管理器上设置scope
属性,因此始终将嵌入式管理器视为具有prototype
范围。
scope
属性用于指定范围设置。 清单5显示了具有不同范围设置的两个bean定义。
清单5.范围示例
<bean id=”prototypeAccount” class=“org.apache.geronimo.osgi.Account”
scope=”prototype”>
<argument value=”4”/>
</bean>
<bean id=”singletonAccount” class=“org.apache.geronimo.osgi.Account”
scope=”singleton”>
<argument value=”5”/>
</bean>
生命周期回调
Bean管理器还可以管理其创建的对象的生命周期,并可以在注入所有属性或销毁所有属性时通知它。 蓝图容器规范定义了两种回调方法:
-
init-method
:指定在注入所有属性后要调用的方法。 -
destroy-method
:指定当蓝图容器销毁对象实例时要调用的方法。
prototype
范围内的bean不支持destroy-method
回调。 销毁那些实例是应用程序的责任。 两种生命周期方法都必须是公共的,不带参数,也不返回值。
清单6显示了一个带有生命周期方法和Blueprint XML bean
条目的Java类的示例,该条目指定了init-method
和destroy-method
属性。
清单6.生命周期回调示例
public class Account {
public Account(long number) {
...
}
public void init() {
...
}
public void destroy() {
...
}
}
<bean id=”accountFour” class=“org.apache.geronimo.osgi.Account”
init-method=”init” destroy-method=”destroy”>
<argument value=”6”/>
<property name=”description” value=”#6 account”/>
</bean>
服务参考经理
服务参考管理器提供对在OSGi服务注册表中注册的服务的访问。 蓝图规范定义了两个服务参考管理器:参考和参考列表。
参考经理
引用管理器提供了一个对象,该对象是服务注册表中注册的实际服务的代理。 代理允许注入的对象保持不变,而后勤服务可以来去去或被其他服务替换。 没有后备服务的代理上的呼叫将阻塞,直到服务可用或发生超时为止。
参考管理器由reference
元素定义。 使用timeout
属性指定代理等待后备服务可用的timeout
。 如果未指定timeout
属性,则假定默认超时为5分钟。 还可以使用blueprint
元素上的default-timeout
属性为Blueprint XML文件中的所有引用管理器更改default-timeout
。 所有超时值均以毫秒为单位; 值0表示无限期超时。
清单7显示了一个简单的引用管理器示例。 服务代理将有30秒的超时时间。
清单7.参考管理器示例
<reference id=”serviceReferenceOne”
interface=”java.io.Serializable”
timeout=”30000”/>
参考清单管理员
引用列表管理器提供一个List
对象,该对象包含服务代理对象或ServiceReference
对象,具体取决于成员类型设置。 所提供的List
对象是动态的,因为随着从服务注册表中添加或删除匹配的服务,它可以增长和收缩。 List
对象是只读的,并且仅支持List
API的子集。
参考列表管理器中的代理与参考管理器中的代理不同。 它们具有固定的后备服务,没有超时,并且如果后备服务不可用,则立即抛出ServiceUnavailableException
。
参考列表管理器由reference-list
元素定义。 使用member-type
属性指定提供的List
对象中member-type
。 member-type
属性支持两个值:
-
service-object
:注入默认情况下假定的服务代理对象列表。 -
service-reference
:插入ServiceReference
对象的列表。
清单8显示了一个简单的引用列表管理器示例。 List
成员将是服务代理。
清单8.引用列表管理器示例
<reference-list id=”serviceReferenceListOne”
interface=”java.io.Serializable”
member-type=”service-object”/>
服务选择和代理
参考和参考列表管理器共享几个属性。 三个共享属性用于服务选择: interface
, component-name
和filter
。
您可以使用interface
属性来指定接口类。 接口类用于两个目的:用于服务选择和用于服务代理。 interface
属性是可选的,但是如果设置,它必须指定接口类。 对于服务选择,接口类用于从使用该接口名称注册的服务注册表中选择服务。 对于服务代理,服务引用管理器返回的代理必须实现该接口类定义的所有方法。 如果未指定interface属性,则代理的行为就好像它实现了没有任何方法的接口一样。
您也可以使用component-name
和filter
属性进行服务选择。 component-name
属性只是将osgi.service.blueprint.compname=<component-name>
表达式添加到选择过滤器的便捷方法。 同样, filter
属性指定要添加到选择过滤器的原始OSGi过滤器表达式。 将interface
, component-name
和filter
属性组合在一起,以创建一个用于服务选择的主要OSGi过滤器表达式。
例如,清单7中用于引用的选择过滤器是( &(objectClass=java.io.Serializable))
,而清单9中用于引用的选择过滤器是(&(objectClass=java.io.Serializable)(osgi.service.blueprint.compname=myAccount)(mode=shared))
。
清单9.服务选择示例
<reference id=”serviceReferenceTwo”
interface=”java.io.Serializable”
component-name=”myAccount”
filter=”(mode=shared)”/>
可用性
服务参考管理器可以要求至少有一个与其选择标准匹配的服务,然后才能继续进行“蓝图容器”初始化。 该需求由availability
属性控制。 availability
属性可以具有两个值:
-
optional
:符合或不符合选择标准的服务。 -
mandatory
:mandatory
至少存在一项符合选择标准的服务。
默认情况下,假定为mandatory
可用性。 可以使用blueprint
元素上的default-availability
属性为Blueprint XML中的所有服务引用管理器更改默认可用性设置。
具有mandatory
可用性且具有匹配服务的服务参考管理器被视为满意。 具有optional
可用性的服务参考管理器始终被认为是满意的,即使它没有任何匹配的服务。 蓝图容器初始化将被延迟,直到满足所有强制性服务参考管理器为止。
重要的是要了解,仅在Blueprint Container初始化期间才考虑mandatory
可用性。 初始化之后,随着服务在任何时候来去去,强制性服务引用可能变得不满意。
清单10显示了具有mandatory
可用性的引用管理器的示例。
清单10.可用性示例
<reference id=”serviceReferenceThree”
interface=”java.io.Serializable”
timeout=”30000”
availability=”mandatory”/>
参考侦听器
两个服务参考管理器都可以具有零个或多个参考侦听器。 引用侦听器是在服务引用管理器选择服务或服务引用管理器不再使用该服务时调用了回调方法的对象。 使用reference-listener
元素指定reference-listener
器。 bind-method
和unbind-method
属性指定回调方法。 提供回调方法的对象可以内嵌在reference-listener
元素中,也可以指定为对顶级管理器的引用。
绑定和取消绑定回调方法都可以具有以下任何签名。 ( anyMethod
表示任意方法名称。)
-
void anyMethod(ServiceReference)
:参数是绑定或未绑定的服务的ServiceReference
对象。 -
void anyMethod(? super T)
:参数是绑定或未绑定的服务对象代理。 类型T必须可以从服务对象中分配。 -
void anyMethod(? super T, Map)
:第一个参数是绑定或未绑定的服务对象代理。 类型T必须可以从服务对象中分配。 第二个参数提供与服务关联的服务属性。
如果引用侦听器有多个用于回调的重载方法,则将调用每个具有匹配签名的方法。
对于引用列表管理器,每次在服务注册表中添加或删除匹配的服务时都会调用侦听器回调。 但是,对于引用管理器,当管理器已绑定到服务并将具有较低排名的匹配服务添加到服务注册表时,将不会调用绑定回调。 同样,绑定管理器的服务消失后,将不会调用unbind回调,并且可以立即将其替换为另一个匹配的服务。
重要的是要了解,当使用引用管理器并与有状态服务交互时,应使用引用侦听器跟踪代理的后备服务,以便适当地管理服务的状态。
清单11显示了一个简单的注册侦听器示例。 ReferenceListener
类具有两个bind方法和一个unbind回调方法,当服务从服务引用列表管理器绑定和解除绑定时,将调用它们。
清单11.引用侦听器示例
public class ReferenceListener {
public void bind(ServiceReference reference) {
...
}
public void bind(Serializable service) {
...
}
public void unbind(ServiceReference reference) {
...
}
}
<reference-list id=”serviceReferenceListTwo” interface=”java.io.Serializable”
availability=”optional”>
<reference-listener
bind-method=”bind” unbind-method=”unbind”>
<bean class=“org.apache.geronimo.osgi.ReferenceListener”/>
</reference-listener>
</reference-list>
服务经理
服务管理器在OSGi服务注册表中注册服务。 如果满足其依赖项中的所有强制性服务引用管理器,则服务管理器将注册和注销该服务。 由于强制服务引用在任何时候都可能变得不令人满意,因此服务管理器将返回一个ServiceRegistration
代理对象,该对象将调用委派给实际的ServiceRegistration
对象。
在初始化期间,蓝图容器为蓝图容器中的每个服务管理器而不是实际的服务对象注册基于ServiceFactory
的服务。 这些服务允许“蓝图容器”延迟对象的创建,因为它们拦截服务请求并仅在需要时实例化实际的服务对象。 实际的服务对象由另一个管理器(通常是bean管理器)提供。 实际的服务对象可以实现OSGi ServiceFactory
接口。
在Blueprint XML中, service
元素定义了服务管理器。 可以使用ref
属性引用提供服务对象的管理器,也可以将其内联到service
元素中。 清单12显示了两种服务:一种具有引用的服务,另一种具有内联管理器。
清单12.服务管理器示例
<service id=”serviceOne” ref=”account” ... />
<service id=”serviceTwo” … >
<bean class=“org.apache.geronimo.osgi.Account”>
<argument value=”123”/>
</bean>
</service>
服务接口
每个服务都必须使用一个或多个接口名称进行注册。 服务的接口名称列表可以显式指定,也可以基于自动导出设置从服务对象自动确定。 可以使用以下任一方式显式设置接口名称:
-
interface
属性,只能指定一个接口名称。 -
interfaces
子元素,允许设置任意数量的接口。
自动导出设置由auto-export
属性指定,并支持以下四个选项。
-
disabled
:如果未指定auto-export
属性,则为默认值。 接口列表必须使用interface
属性或interfaces
子元素指定。 -
interfaces
:使用服务类及其任何超类实现的所有公共接口注册服务。 -
class-hierarchy
:使用服务类及其任何公共超级类注册服务。 -
all-classes
:结合了interfaces
和class-hierarchy
选项。
清单13显示了使用三种指定服务接口的方法的服务。 在此示例中,使用一个Serializable
接口类注册serviceOne
和serviceTwo
服务,而使用MyAccount
, Account
和Serializable
类注册serviceThree
服务。
清单13.服务接口示例
public class MyAccount extends Account implements java.io.Serializable {
...
}
<bean id=”myAccount” class=”org.apache.geronimo.osgi.MyAccount”>
<argument value=”7”/>
<property name=”description” value=”MyAccount”/>
</bean>
<service id=”serviceOne” ref=”myAccount” interface=”java.io.Serializable”/>
<service id=”serviceTwo” ref=”myAccount”>
<interfaces>
<value>java.io.Serializable</value>
</interfaces>
</service>
<service id=”serviceThree” ref=”myAccount” autoExport=”all-classes”/>
服务属性
服务也可以使用可以使用service-properties
子元素指定的一组属性进行注册。 service-properties
元素包含代表各个属性的多个entry
子元素。 使用key
属性指定属性键,但是可以将属性值指定为value
属性或在元素内联。 服务属性值可以具有不同的类型,但仅允许使用基元,基元包装器类,集合或基元类型的数组。
清单14显示了具有两个服务属性的服务注册的示例。 active
服务属性的值是java.lang.Boolean
类型。 mode
属性为String
类型。
清单14.服务属性示例
<service id=”serviceFour” ref=”myAccount” autoExport=”all-classes”>
<service-properties>
<entry key=”mode” value=”shared”/>
<entry key=”active”>
<value type=”java.lang.Boolean”>true</value>
</entry>
</service-properties>
</service>
如果为服务提供服务对象的管理器是顶级管理器,则会将osgi.service.blueprint.compname
属性自动添加到服务属性。 osgi.service.blueprint.compname
属性的值是提供服务实例的顶级管理器的ID。 例如,给定清单14中的服务示例, osgi.service.blueprint.compname
属性的值将设置为myAccount
。
服务排名
您可以使用ranking
属性来为服务提供特定的排名。 如果未指定等级属性,则该服务将不进行等级注册。 在这种情况下,OSGi框架将0
假定为服务的默认排名。
带有排名的服务注册示例如下所示。
清单15.服务排名示例
<service id=”serviceFive” ref=”myAccount” auto-export=”all-classes” ranking=”3”/>
注册监听器
服务管理器可以具有零个或多个注册侦听器 ,这些对象具有在服务注册之后或注销服务之前立即调用回调方法的对象。 使用registration-listener
子元素指定registration-listener
器。 registration-method
和unregistration-method
属性指定回调方法。 提供回调方法的对象可以内联在registration-listener
元素中,或指定为对顶级管理器的引用。
注册和取消注册回调方法的签名取决于服务对象是否实现ServiceFactory
接口。 如果服务实现ServiceFactory
接口,则这两个方法都必须具有void anyMethod(ServiceFactory, Map)
签名,其中anyMethod
表示任意方法名称。
如果服务未实现ServiceFactory
接口,则这两个回调方法都必须与void anyMethod(? super T, Map)
签名匹配,在该签名中,可以从服务对象的类型中分配类型T。 回调方法的第一个参数是服务对象的实例,第二个参数是注册属性。 如果注册侦听器有多个用于回调的重载方法,则将调用每个具有匹配签名的方法。
清单16显示了一个简单的注册侦听器示例。
清单16.注册侦听器示例
public class RegistrationListener {
public void register(Account account, Map properties) {
...
}
public void unregister(Account account, Map properties) {
...
}
}
<service id=”serviceSix” ref=”myAccount” auto-export=”all-classes”>
<registration-listener
registration-method=”register” unregistration-method=”unregister”>
<bean class=“org.apache.geronimo.osgi.RegistrationListener”/>
</registration-listener>
</service>
环境经理
蓝图容器规范还定义了许多特殊的环境管理器,这些管理器已设置ID并提供对环境组件的访问。 它们没有XML定义,因此不能被覆盖,因为它们的ID是保留的,不能与其他管理器一起使用。 由环境管理员提供的对象只能使用引用注入到其他管理员中。 蓝图容器规范定义了四个环境管理器:
-
blueprintBundle
:提供包的Bundle
对象。 -
blueprintBundleContext
:提供捆绑软件的BundleContext
对象。 -
blueprintContainer
:为BlueprintContainer
包提供BlueprintContainer
对象。 -
blueprintConverter
:为捆绑包提供Converter
对象,该捆绑包提供对Blueprint容器类型转换工具的访问。 类型转换有更多信息。
清单17显示了一个简单的示例,其中将blueprintBundle
环境管理器提供的Bundle
对象注入到accountManagerOne
bean中。
清单17.环境管理器示例
public class AccountManager {
public void setManagerBundle(Bundle bundle) {
...
}
}
<bean id=”accountManagerOne” class=”org.apache.geronimo.osgi.AccountManager”>
<property name=”managerBundle” ref=”blueprintBundle”/>
</bean>
对象值
蓝图容器规范定义了许多XML元素,这些元素描述了不同类型的对象值。 这些XML值元素在管理器定义中使用。 例如,可以在Bean管理器中使用它们来指定参数或属性值,或者在服务管理器中使用它们来指定服务属性的值。 XML值元素将转换为实际值对象,并注入到管理器组件中。
ref
元素定义对顶级管理器的引用。 component-id
属性指定顶级管理器的ID。 注入的值将是引用的管理器返回的对象。
清单18显示了ref
值元素的示例。 该accountOne
bean实例注入managedAccount
的财产accountManagerTwo
豆。
清单18.参考值示例
public class AccountManager {
...
public void setManagedAccount(Account account) {
...
}
}
<bean id=”accountOne” class=“org.apache.geronimo.osgi.Account”>
<argument value=”1”/>
<property name="description" value="#1 account"/>
</bean>
<bean id=”accountManagerTwo” class=“org.apache.geronimo.osgi.AccountManager”>
<property name=”managedAccount”>
<ref component-id=”accountOne”/>
</property>
</bean>
idref
元素定义顶级管理器的ID。 注入的值是component-id
属性指定的component-id
。 idref
元素用于确保在激活管理器之前实际存在指定ID的管理器。
value
元素表示要根据该元素的字符串内容创建的对象。 您可以使用可选的type
属性来指定字符串内容应转换为的类型。 如果未指定type
属性,则字符串内容将转换为正在注入的类型。
null
元素表示Java null。
list
, set
和array
元素是集合,分别代表java.util.List
对象, java.util.Set
对象和Object[]
数组。 这些集合的子元素可以是本节中描述的任何XML值元素。 可以在这些元素上设置可选的value-type
属性,以指定集合子元素的默认类型。
清单19中的示例显示了如何将XML值元素组合在一起以创建列表。 创建的列表将包含以下四个项目:
- 一个“ 123”
String
- 具有456值的
java.math.BigInteger
对象 - 空值
- 一个具有两个类型为
java.lang.Integer
值的java.util.Set
对象
清单19.复杂列表值示例
<list>
<value>123</value>
<value type=”java.math.BigInteger”>456</value>
<null/>
<set value-type=”java.lang.Integer”>
<value>1</value>
<value>2</value>
</set>
</list>
props
元素表示一个java.util.Properties
对象,其中的键和值是String
类型的。 prop
子元素代表各个属性。 使用key
属性指定属性键,但是可以将属性值指定为value
属性或元素的内容。
清单20显示了props
value元素的示例。
清单20. Properties值示例
<props>
<prop key=”yes”>good</prop>
<prop key=”no” value=”bad”/>
</props>
map
元素表示一个java.util.Map
对象,其中键和值可以是任意对象。 entry
子元素代表各个属性。 键可以指定为key
属性, key-ref
属性,也可以内联在key
子元素中。 该值可以指定为value
属性, value-ref
属性或内联。 可以将内联值指定为本节中描述的任何XML值元素。 但是,可以将内联键指定为除null
元素之外的任何XML值元素。 蓝图规范中的map
元素中不允许使用空键。 key-ref
和value-ref
属性指定顶级管理器的ID,并用于从指定的管理器获取对象作为属性键或值。 map
元素可以指定key-type
和value-type
属性,以定义键和值的默认类型。
清单21显示了map
值元素的示例。 它还显示了如何以几种方式构造map
对象的条目。 创建的map
对象将包含以下条目:
- 一个myKey1
String
键,它映射到myValueString
。 - 作为
account
Bean管理器返回的对象的键被映射到myValueString
。 - 一个键(它是一个具有123值的
java.lang.Integer
对象)被映射到myValueString
。 - myKey2
String
键映射到一个值,该值是account
bean管理器返回的对象。 - myKey3
String
键映射到一个值为345的java.lang.Long
对象的值。 - 一个键是urn:ibm值的
java.net.URI
对象,它映射到一个值是http://ibm.com值的java.net.URL
对象。
清单21. map
值示例
<map>
<entry key=”myKey1” value=”myValue”/>
<entry key-ref=”account” value=”myValue”/>
<entry value=”myValue”>
<key>
<value type=”java.lang.Integer”>123</value>
<key/>
</entry>
<entry key=”myKey2” value-ref=”account”>
<entry key=”myKey3”>
<value type=”java.lang.Long”>345</value>
</entry>
<entry>
<key>
<value type=”java.net.URI”>urn:ibm</value>
<key/>
<value type=”java.net.URL”>http://ibm.com</value>
</entry>
</map>
每个经理也可以作为值内联。 清单22显示了一个内联的bean管理器示例。
清单22.内联管理器值示例
<bean id=”accountManagerThree” class=“org.apache.geronimo.osgi.AccountManager”>
<property name=”managedAccount”>
<bean class=“org.apache.geronimo.osgi.Account”>
<argument value=”10”/>
<property name="description" value="Inlined Account"/>
</bean>
</property>
</bean>
类型转换
在注入期间,蓝图容器将XML值元素转换为实际对象。 它根据注入的属性的类型转换元素。 例如,在清单2中 ,Blueprint容器将123 String值转换为long
值。 蓝图容器提供了许多内置转换,例如转换:
- 将字符串值分为所有原始类型,包装器类型,或具有采用String值的公共构造函数的任何类型。
-
array
元素放入集合对象(具有兼容的成员类型)。 -
set
元素list
或set
为数组对象(具有兼容的成员类型)。
蓝图容器还支持泛型。 如果泛型信息可用,则蓝图容器将使用该信息来执行转换。 例如,在清单23中, list
元素将被转换为java.util.Long
对象的列表。
清单23.泛型转换示例
public class AccountManager {
...
public void setAccountNumbers(List<Long> accounts) {
...
}
}
<bean id=”accountManagerFour” class=“org.apache.geronimo.osgi.AccountManager”>
<property name=”accountNumbers”>
<list>
<value>123</value>
<value>456</value>
<value>789</value>
</list>
</property>
</bean>
除了内置的转换,Blueprint捆绑包还可以提供自己的转换器。 定制转换器是Bean管理器,提供了实现Blueprint的Converter
接口的对象。 自定义转换type-converters
在blueprint
元素下的type-converters
元素内指定。 The type converters are initialized first during Blueprint Container initialization so other managers can take advantage of the custom converters. The Blueprint Container specification has more information about writing custom converters.
Experimenting with Blueprint
To experiment with Blueprint applications, you need two things: an OSGi platform and the Blueprint Container implementation. In this article, we will use Equinox as the OSGi platform, but others — such as Apache Felix — would work just as well. For the Blueprint Container, we will use an implementation from the Apache Aries incubator project. The Blueprint implementation in Aries was originally developed at the Apache Geronimo project, but has been moved to Aries, where it is being actively developed.
The attached sample provides a good starting point for experimenting with Blueprint. It contains two modules: blueprint-sample
and blueprint-assembly
. The blueprint-sample
module is a sample Blueprint bundle. It contains many of the Java classes and Blueprint XML definitions shown in this article. The blueprint-assembly
module packages the Equinox framework, the Apache Aries Blueprint implementation, and the sample bundle together in an easy-to-start container.
Building the sample
Download and unzip the attached sample source to a directory of your choice. Use Apache Maven to build the sample source. Execute the commands in Listing 24 to build the sample.
Listing 24. Building the sample
cd sample
mvn install
Maven will automatically build both modules in the sample. Once the entire sample is successfully built, the target
directory of the blueprint-assembly
module will contain a number of JAR files. It will contain the Apache Aries Blueprint implementation, the sample bundle and a couple other JARs that provide logging capabilities for the OSGi framework. It will also contain the osgi-3.5.0.v20090520.jar file, which provides the Equinox framework. Once started, the Equinox framework will automatically install and start all the other JARs in the target directory. To start the Equinox framework, execute the commands in Listing 25.
Listing 25. Starting Equinox
cd blueprint-assembly/target
java -jar osgi-3.5.0.v20090520.jar -console
The Equinox console will appear after successful startup. Use the ss
command to display the installed bundles; Figure 1 shows the output of the ss
command.
Figure 1. Installed bundles output
![The Equinox console appears after successful startup](https://i-blog.csdnimg.cn/blog_migrate/20e680ccc23c9ed4869aa4266ffba5e4.png)
Running the sample bundle
The sample bundle will be automatically installed in Equinox framework, but will not be started. To start the sample bundle, execute the start 5
command in the Equinox console; the number 5 is the ID of the org.apache.aries.sample_1.0.0.SNAPSHOT
sample bundle. Once the sample bundle is successfully started, you should see the following output in the console, as shown in Figure 2.
Figure 2. Sample bundle output
摘要
The Blueprint Container specification, introduced in the latest OSGi specification, provides a simple and easy programming model for creating dynamic applications in the OSGi environment without adding complexity to the Java code. With the Aries Blueprint Container implementation, you can start building Blueprint-based applications today.
翻译自: https://www.ibm.com/developerworks/opensource/library/os-osgiblueprint/index.html
osgi容器