OSGi容器中Bundle之间Synchronous Communication
OSGi Core定义了一个服务层,提供了一个Bundle之间交互的简单机制,通过注册Java Object 至OSGi service registry。 Blueprint Container
(1) Blueprint Configuration
默认配置文件位于:ProjectDir/src/main/resources/OSGI-INF/blueprint
默认XML文件命名空间:
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> ... </blueprint>
自定义配置文件地址:
Bundle-Blueprint: lib/account.xml, security.bp, cnf/*.xml
Mandatory dependencies:
OSGi Service 中Dependencies默认是必须的,但可通过设置reference和reference-list元素的availability为optional
来改变这中现象。正常情况下,当Bluepring Container初始化时,通过一定范围的时间来允许Dependencies
Resolve, 该时间么哦人为:5秒,可通过下面的方式自定义:
Bundle-SymbolicName: org.fusesource.example.osgi-client; blueprint.graceperiod:=true; blueprint.timeout:= 10000
(2) Defining a Service Bean
(3) Exporting a Service
1. Exporting with a single interface
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <bean id="savings" class="org.fusesource.example.SavingsAccountImpl" /> <service ref="savings" interface="org.fusesource.example.Account" /> </blueprint>
2. Exporting with multiple interfaces
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <bean id="savings" class="org.fusesource.example.SavingsAccountImpl" /> <service ref="savings"> <interfaces> <value>org.fusesource.example.Account</value> <value>org.fusesource.example.SavingsAccount</value> </interfaces> </service> </blueprint>
注意:interface和interfaces不能同时在service元素中使用。
3. Exporting with auto-export
例如:下面的代码中Blueprint将自动注册所有SavingsAccountImpl实现的public接口:
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <bean id="savings" class="org.fusesource.example.SavingsAccountImpl" /> <service ref="savings" auto-export="interfaces" /> </blueprint>
其中auto-export默认值为:disabled,其他可选值为:
interfaces:注册该类实现的所有public的接口;
class-hierarchy:注册该类自己以及他的父类,但不包含Object类;
all-classes:注册该类自己以及他的父类,同时包括该类实现的接口。
4. Setting service properties
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <bean id="savings" class="org.fusesource.example.SavingsAccountImpl" /> <service ref="savings" auto-export="interfaces" ranking="10"> <service-properties> <beans:entry key="bank.name" value="HighStreetBank" /> </service-properties> </service> </blueprint>
说明:A. 注册的service默认的Properties有:osgi.service.blueprint.compname值为service bean 的id
B. service.ranking 是系统自动设置。
C. 当系统查找服务时返回对个匹配的服务时,默认选择ranking值最高的服务,因此可配置该属性用以服务
之间的区分。
5. Specifying a registration listener
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" .> <bean id="listenerBean" class="org.fusesource.example.Listener" /> <service ref="savings" auto-export="interfaces"> <registration-listener ref="listenerBean" registration-method="register" unregistration-method="unregister" /> </service> </blueprint>
//Java package org.fusesource.example; public class Listener { public void register(Account service, java.util.Map serviceProperties) { } public void unregister(Account service, java.util.Map serviceProperties) { } }
说明:register和unregister方法的参数,第一个参数可以是service class或service class 实现的接口,因为该
参数包含service instance, 如果该service bean 被声明为property, 在注册的时候是没有service instance可用
的,因此此时该参数的值为null.
第二个参数可以是java.util.Map或java.util.Dictionary,这个Map包含service 注册时的Properties.
(4) Importing a Service
使用reference和reference-list元素Import Service, 两者之间的区别是:reference用于访问stateless service,
而reference-list用于访问stateful service.
1. Matching by interface (stateless)
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <reference id="savingsRef" interface="org.fusesource.example.SavingsAccount" /> <bean id="client" class="org.fusesource.example.client.Client"> <property name="savingsAccount" ref="savingsRef" /> </bean> </blueprint>
package org.fusesource.example.client; import org.fusesource.example.SavingsAccount; public class Client { SavingsAccount savingsAccount; // Bean properties public SavingsAccount getSavingsAccount() { return savingsAccount; } public void setSavingsAccount(SavingsAccount savingsAccount) { this.savingsAccount = savingsAccount; } }
2. Matching by interface (stateful)
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <reference-list id="savingsListRef" interface="org.fusesource.example.SavingsAccount" /> <bean id="client" class="org.fusesource.example.client.Client"> <property name="savingsAccountList" ref="savingsListRef" /> </bean> </blueprint>
package org.fusesource.example.client; import org.fusesource.example.SavingsAccount; public class Client { java.util.List<SavingsAccount> accountList; // Bean properties public java.util.List<SavingsAccount> getSavingsAccountList() { return accountList; } public void setSavingsAccountList(java.util.List<SavingsAccount> accountList) { this.accountList = accountList; } }
3. Matching service properties with a filter
<reference id="savingsRef" interface="org.fusesource.example.SavingsAccount" filter="(bank.name=HighStreetBank)" /> <reference-list id="savingsRef" interface="org.fusesource.example.SavingsAccount" filter="(bank.name=HighStreetBank)" />
4. Specifying whether mandatory or optional
默认值:mandatory
<reference id="savingsRef" interface="org.fusesource.example.SavingsAccount" availability="mandatory" />
5. Specifying a reference listener
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"> <reference id="savingsRef" interface="org.fusesource.example.SavingsAccount"> <reference-listener bind-method="onBind" unbind-meth od="onUnbind"> <bean class="org.fusesource.example.client.Listener" /> </reference-listener> </reference> <bean id="client" class="org.fusesource.example.client.Client"> <property name="savingsAcc" ref="savingsRef" /> </bean> </blueprint>
package org.fusesource.example.client; import org.osgi.framework.ServiceReference; public class Listener { public void onBind(ServiceReference ref) { System.out.println("Bound service: " + ref); } public void onUnbind(ServiceReference ref) { System.out.println("Unbound service: " + ref); } }