OSGi Service Registery你知多少?
1. 发布服务可以关联一些属性。
<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>
2. 每个以Spring Bean发布成服务都会有一个属性名为org.springframework.osgi.bean.name,对应的值为目标Bean的name。
<service ref="beanToPublish" interface ="com.xyz.MessageService"/>
这个服务就会有一个属性org.springframework.osgi.bean.name,值为beanToPublish。
3. Spring DM引入一种Bean的作用域,叫bundle scope。当导出服务的Bean加了这个作用域后,导入这个服务的Bundle会创建一个新的服务Bean实例。
<service ref="beanToBeExported" interface ="com.xyz.MessageService"/> <bean id="beanToBeExported" scope="bundle" class ="com.xyz.MessageServiceImpl"/>
4. Controlling The Set Of Advertised Service Interfaces For An Exported Service.
当有一个Bean服务存在多个接口时,需要将接口都导出:
<service ref="beanToBeExported"> <interfaces> <value>com.xyz.MessageService</value> <value>com.xyz.MarkerInterface</value> </interfaces> </osgi:service>
or
<service ref="beanToBeExported" auto-export="interfaces"/>
auto-export有四种值:
disabled :如果 auto-export 属性未被指定,则该选项为默认值。接口列表必须使用interface 属性或 interfaces 子元素指定。
interfaces :使用由服务类或其任何超类实现的所有公共接口注册服务。
class-hierarchy :使用服务类或其任何公共超类注册服务。
all-classes :结合 interfaces 和 class-hierarchy 选项。
注册服务的一些属性:
depends-on :
<service ref="beanToBeExported" interface ="com.xyz.MyServiceInterface" depends-on="myOtherComponent"/>
配置beanToBeExported服务所依赖的组件myOtherComponent初始化。
context-class-loader :
用于配置使用第三方的classloader来加载服务。
ranking :
默放为0,如果存在多个可用的服务接口,那么返回具有最大的ranking值的服务。如果ranking值相同,刚返回service id小的那个。
<service ref="beanToBeExported" interface ="com.xyz.MyServiceInterface" ranking="9"/>
5. 多接口服务引用
<reference id="importedOsgiService"> <interfaces> <value>com.xyz.MessageService</value> <value>com.xyz.MarkerInterface</value> </interfaces> </reference>
这个reference的Bean是实现了MessageService,MarkerInterface接口的。
引用服务的一些属性
filter属性
<reference id="asyncMessageService" interface ="com.xyz.MessageService" filter="(asynchronous-delivery=true)"/>
过滤服务属性asynchronous-delivery为true的服务。
bean-name属性
<osgi:reference id="messageService" interface ="com.xyz.MessageService" bean-name="messageServiceBean"/>
返回服务Bean的Id为messageServiceBean的服务。
cardinality属性
<osgi:reference id="messageService" interface ="com.xyz.MessageService" cardinality="1..1"/>
默认值为1..1,说明总是有一个这样的服务存在。0..1说明不需要一直存在这样一个服务。
depends-on:
当depends-on属性Bean实例化后,这个服务才能查找该服务。
context-class-loader:
与上对应。如果两边都有,最后启作用的是exporter那端的。
timeout:
等待服务多少秒,默认300秒。
List,set引用服务支持属性
interface filter bean-name cardinality context-class-loader
cardinality取值为0..N,1..N,前面说明可以不存在,后面说明至少存在一个。
注意: 当一个Bundle暴露SubInterface接口服务,而另一个Bundle引入SuperInterface接口是不匹配的。
当注册的服务中有接口,类等,能通过greedy-proxying创建代理访问导入服务中的的所有包含在该Bundle中类。
<list id="services" interface ="com.xyz.SomeService" greedy-proxying="true"/>
for (Iterator iterator = services.iterator(); iterator.hasNext();) {
SomeService service = (SomeService) iterator.next();
service.executeOperation();
// if the service implements an additional type
// do something extra
if (service instanceof MessageDispatcher) {
((MessageDispatcher)service).sendAckMessage();
}
}
6. 服务监听Service Listener:
<service ref="beanToBeExported" interface ="SomeInterface">
<registration-listener ref="myListener" registration -method="serviceRegistered" unregistration -method="serviceUnregistered"/>
<registration- listener registration -method="register">
<bean class ="SomeListenerClass"/>
</registration-listener>
</service>
public void anyMethodName(ServiceType serviceInstance, Map serviceProperties);
public void anyMethodName(ServiceType serviceInstance, Dictionary serviceProperties);
ServiceType为服务接口interface,serviceProperties保存着这个服务的所有属性,兼容性考虑的话,可以选Dictionary。
有另一种方法,不鼓励这样用,那就是实现Spring DM特定接口OsgiServiceRegistrationListener,这样做的好处是省去了声明registration-method,unregistration-method,坏处是你的类与Spring有引用关系,与JAVA简单POJO类编程。
Dealing With The Dynamics Of OSGi Imported Services
An example of declaring a listener that implements OsgiServiceLifecycleListener:
<reference id="someService" interface ="com.xyz.MessageService">
<listener ref="aListenerBean"/>
</reference>
An example of declaring an inline listener bean with custom bind and unbind methods:
<reference id="someService" interface ="com.xyz.MessageService">
<listener bind-method="onBind" unbind-method="onUnbind">
<beans:bean class ="MyCustomListener"/>
</listener>
</reference>
Listener Attributes:
ref bind-method unbind-mehtod
Listener And Service Proxies:
Spring管理这个服务,但是调用这个服务的时候实质是一个代理。这样做的原因是防止Listener持有一个服务的强引用。Lisenter感兴趣的是监听服务而不是依赖对等实例,更加关注服务接口,而不是他的身份,服务属性和服务跟踪。
7. 服务引用可以排序
<set id="myServices" interface ="com.xyz.MyService" comparator-ref="someComparator"/>
<list id="myOtherServices" interface ="com.xyz.OtherService">
<comparator>
<beans:bean class ="MyOtherServiceComparator"/>
</comparator>
</list>
Comparator-ref是一个实现了java.util.Comparator接口的Bean。
<list id="myServices" interface ="com.xyz.MyService"> <comparator><natural basis="services"/></comparator> </list> <set id="myOtherServices" interface ="com.xyz.OtherService"> <comparator><natural basis="service-references"/></comparator> </set>
默认提供的一些排序,详细可以去了解下。
服务最佳实践
1. 在listener中不要执行太长的活动,因为这个方法是同步的,太长将会影响这个listener监听其他事件。
2. 创建自己的listener,不要引用Spring DM 的API。
3. 如果listener重复声明bind/unbind方法,可以考虑写一个通用的可重用的Bean。
4. 服务属性优先java.util.Map而不是java.util.Dictionary。
5. 重载方法要小心,因为当服务类型匹配方法服务类型的时候,该方法就会执行
public class MyListener {
void register(Object service, Map properties);
void register(Collection dataService, Map properties);
void register(SortedSet orderedDataService , Map properties);
}
Object type - will match all services for which the listener is triggered. This method will be always called.
Collection type - if this method is called, the Object method is also called.
SortedSet type - if this method is called, then both the Object and Collection methods are called.
Service Importer Global Defaults
default - timeout
<beans xmlns="http://HdhCmsTestspringframework.org/schema/beans"
xmlns:xsi ="http://HdhCmsTestw3.org/2001/XMLSchema-instance"
xmlns:osgi ="http://HdhCmsTestspringframework.org/schema/osgi"
osgi: default -timeout="5000">
<reference id="someService" interface ="com.xyz.AService"/>
<reference id="someOtherService" interface ="com.xyz.BService" timeout ="1000"/>
</beans:beans>
default - cardinality
< beans:beans
xmlns ="http://HdhCmsTestspringframework.org/schema/osgi"
xmlns:xsi ="http://HdhCmsTestw3.org/2001/XMLSchema-instance"
xmlns:beans ="http://HdhCmsTestspringframework.org/schema/beans"
xmlns:osgi ="http://HdhCmsTestspringframework.org/schema/osgi"
osgi: default -cardinality="0..X"
default -lazy-init="false">
<reference id="someService" interface ="com.xyz.AService"/>
<set id="someSetOfService" interface ="com.xyz.BService"/>
<list id="anotherListOfServices" interface ="com.xyz.CService" cardinality="1..N"/>
</beans:beans>
标签: OSGI , Service Registery , Service Listener , OSGi Best Practice
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于OSGi Service Registery你知多少?的详细内容...