1、输出Spring Bean作为OSGi服务 Service元素被用作将一个Bean定义为一个被输出OSGi服务,你至少需要指定将被输出的Bean和服务将对外提供的接口。 例如,下面的声明: <service ref="beanToPublish" interface="com.xyz.MessageService"/> 输出一个名为beanToPublish的Bean为服务,这个服务具有接口com.xyz.MessageService。这个被发布的服务将会有一个名为org.springframework.osgi.bean.name的Service属性,属性值为Bean的名称(在本例中为beanToPublish)。 被Service元素定义的Bean的类型是org.osgi.framework.ServiceRegistration,它是在OSGi 服务注册表中注册输出Bean而产生的ServiceRegistration对象。给这个Bean一个ID属性,你就可以将这个ServiceRegistration对象的引用注入到任何其他Bean中,例如: <service id="myServiceRegistration" ref="beanToPublish" interface="com.xyz.MessageService"/> 作为输出一个命名Bean的可选方案,被输出的到Serviec注册表的Bean可以在service元素里定义为一个内部匿名Bean。典型地以beans命名空间作为顶级命名空间,如下使用方式: <osgi:service interface="com.xyz.MessageService"> <bean class="SomeClass"> ... </bean> </osgi:service> 如果被输出的Bean实现了org.osgi.framework.ServiceFactory接口,那么按照《OSGI Service Platform Core规范》5.6节所述,ServiceFactory约束将生效。作为实现这个接口的另一个可选方案,Spring Dynamic Modules 引入了一个新的Bean作用域:bundle作用域。当一个具有bundle作用域的Bean被输出为一个OSGi服务,那么在每个客户bundle(服务调用者)通过OSGi服务注册表获得一个该服务的引用时,都会创建一个这个Beann的实例。当调用服务的Bundle停止时,与之相关联的Bean实例会被清理 掉。要声明一个Bean具有bundle作用域仅需使用bean元素的scope属性: <osgi:service ref="beanToBeExported" interface="com.xyz.MessageService"/> <bean id="beanToBeExported" scope="bundle" class="com.xyz.MessageServiceImpl"/>
这里有一些选项用于在输出服务已经被注册的情况下指定服务接口(或者服务接口集)。如上所述,最简单的机制就是使用interface属性来指定一个全限定接口名。注册一个提供多个接口的服务可以使用嵌套的interfaces元素来代替interface属性: <osgi:service ref="beanToBeExported"> <osgi:interfaces> <value>com.xyz.MessageService</value> <value>com.xyz.MarkerInterface</value> </osgi:interfaces> </osgi:service> 通过使用auto-export属性你可以不用再分析对象的类层次和接口,根本不用明确声明服务接口。 auto-export属性可选值有如下4个: disabled:默认选项;服务接口自动检测不会被启动,必须使用interface或interfaces元素。 interfaces:服务将注册具有该bean所实现的所有Java接口。 class-hierarchy:服务将注册该bean 的类及其父类。 all-classes:服务将注册该bean的类和父类,并且注册该bean所实现的所有接口。 例如,如果想要自动注册一个bean所有它支持的接口,你需要这样声明: <service ref="beanToBeExported" auto-export="interfaces"/> 下面给出对应的接口层次: public interface SuperInterface {} public interface SubInterface extends SuperInterface {} 在OSGi规范下,寻找支持SuperInterface的接口时,一个注册为支持SubInterface接口的服务不会被认为是一个匹配的结果。由于这个原因,使用interfaces元素或auto-export=”interfaces”时,这是个关于输出所有被明确注册的服务支持的接口一个不错的实践
service-properties元素必须至少嵌套包含一个Spring 的beans命名空间下的entry元素,例如: <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> 在OSGi Configuration Administration Service中注册的属性可以输出为注册服务的属性,Spring Dynamic Modules Roadmap包含了对此支持
<service ref="beanToBeExported" interface="com.xyz.MyServiceInterface" depends-on="myOtherComponent"/>
context-class-loader属性的可选值有:unmanaged(默认为此项)和service-provider。当service-provider值被指定时,Spring Dynamic Modules会确保context class loader可以看见在输出服务的bundle的class path上的所有资源。 当把context-class-loader的值设置为service-provider时,service对象会代理class loader。如果服务声明任何实际类,那么将需要CGLIB类库支持。
在用服务注册表注册一个服务时,你可能会随便指定一个服务ranking(见《OSGI Platform Core规范》5.2.5)。当一个bundle在服务注册表中寻找服务时,具有最高ranking值的那个服务将被返回。ranking的默认值为0。要为注册服务明确地指定ranking值,使用可选属性:ranking。 <service ref="beanToBeExported" interface="com.xyz.MyServiceInterface" ranking="9"/>
在一个服务被注销后(或注册后),对它有依赖的bundle不再是satisfied状态,如果你需要做一些操作,那么可以定义一个监听bean:使用嵌套的registration-listener元素。 注册监听器的声明必须使用ref属性指向一个顶级Bean的声明,或者声明一个内联的匿名监听bean。例如: <service ref="beanToBeExported" interface="SomeInterface"> <registration-listener ref="myListener"--1 registration-method="serviceRegistered" --2 unregistration-method="serviceUnregistered"/>-- 2 <registration-listener registration-method="register"> --3 <bean class="SomeListenerClass"/>-- 4 </registration-listener> </service> --1指向一个顶级Bean声明的监听器声明 --2指出注册和注销方法 --3声明这个监听器只有一个自定义的注册方法 --4嵌套监听bean的声明 可选属性registration-method和unregistration-method为监听bean指定在注册和注销后调用的方法。一个注册或注销回调函数必须符合如下的格式之一: public void anyMethodName(ServiceType serviceInstance, Map serviceProperties); public void anyMethodName(ServiceType serviceInstance, Dictionary serviceProperties); ServiceType 可以是任何与输出服务接口兼容的类型。 register回调函数会在系统启动时初次注册服务时调用,也会在后续的服务重新注册时调用。unregister回调函数会在无论何种原因引起服务注销时调用(例如所持有的bundle停止)。 只有在一个具有兼容类型的服务将被注册或注销时,Sping-DM才会使用被声明的ServiceType 参数类型并调用registration/unregistration方法。 serviceProperties 使用一个map来存储所有注册/注销服务的属性。为了保留和OSGi规范的兼容性,如果必要,这个参数可以是被换成java.util.Dictionary.
监听器可以实现OsgiServiceRegistrationListener接口并声明自定义方法,这样Spring-DM接口方法会被优先调用,然后调用自定义方法。 |
|
来自: 怀旧妞妞 > 《spring动态模型》