1.Configuring collections:the list tag for lists and the set tag for sets
<beans (...)>
<osgi:list id="testServices"
interface="com.manning.sdmia.springdm.service.TestService"/>
</beans>
Attributes of the list and set tags:
(1)interface:Specifies the identifier for the service and must correspond to a class or interface
name. This is the same use as for the reference tag.
(2)filter:Can be used as an expression to select a subset of services to be matched. This is the
same use as for the reference tag.
(3)bean-name:Allows you to select the service with the bean-name property set. This is the
same use as for the reference tag.
(4)context-classloader:Can be used to automatically manage the TCCL when calling a referenced
service. This is the same use as for the reference tag.
(5)availability:Specifies whether the collection can be empty. A value of optional means that
the collection can be empty and services are optional; a value of mandatory (which is the default)
requires at least one service in the collection.
(6)comparator-ref:Specifies the comparator to be used to sort collection.
(7)greedy-proxying:
Specifies whether service proxies within the collection can be seen only as service classes (value
false) or as all classes exported by service (value true).
(8)member-type:Specifies which type of object may be added to the collection. With a value of
service-object (the default), Spring DM service proxies are present in the collection; with a value
of service-reference, the collection contains ServiceReference objects.
2. Sorting collections
Spring DM allows you to sort service collections within list and set tags by using the Comparator
interface. Comparators can be configured directly within the Spring container and referenced
when configuring service-based collections. These two ways to configure comparators are
supported by Spring DM:
■ Referencing an existing comparator bean by its identifier through the comparator-ref attribute
■ Configuring a comparator as a nested bean through the nested comparator element
示例:
public class MyCustomComparator implements Comparator<TestService> {
public int compare (TestService o1, TestService o2) {
//Implementing the compare processing
(...)
}
}
Configuring custom comparators for service collections:
<bean id="customComparator"
class="com.manning.sdmia.springdm.service.sorting.MyCustomComparator"/>
<osgi:set id="testServiceSet" interface="com.manning.sdmia.springdm.service.TestService"
comparator-ref="customComparator"/>
<osgi:list id="testServiceList" interface="com.manning.sdmia.springdm.service.TestService">
<osgi:comparator>
<bean class="com.manning.sdmia.springdm.service
.sorting.MyCustomComparator"/>
</osgi:comparator>
</osgi:list>
Instead of providing your own comparators, Spring DM allows you to use natural comparators,
through the natural tag of the osgi namespace. This tag has a basis attribute that accepts one
of two values, specifying which sorting strategy you want to use:
■ services —The ordering is based on the service instances, which must implement the
Comparable interface.
■ service-references —The ordering is based on the ServiceReferences (which are automatically
Comparable)
Configuring natural comparators for service collections:
<osgi:list id="testServiceList" interface="com.manning.sdmia.springdm.service.TestService">
<osgi:comparator>
<osgi:natural basis="services"/>
</osgi:comparator>
</osgi:list>
<osgi:set id="testServiceSet" interface="com.manning.sdmia.springdm.service.TestService">
<osgi:comparator>
<osgi:natural basis="service-references"/>
</osgi:comparator>
</osgi:set>
3. Greedy proxying
The greedy proxy feature of Spring DM makes it possible to cast services in collections to all of
the exposed interfaces that a service supports. The only restriction is that the interfaces used
must be visible to the component within OSGi. Once greedy proxying is enabled, you can cast
your service reference to any of the exposed interfaces and classes visible to your component.
示例:
<osgi:list id="testServiceList" interface="com.manning.sdmia.springdm.service.TestService"
greedy-proxying="true" />
Using the greedy proxying feature in code:
for (Iterator iterator = testServiceList.iterator(); iterator.hasNext();) {
TestService service = (TestService) iterator.next();
(...)
if (service instanceof AnotherInterface) {
AnotherInterface anotherServiceInterface = (AnotherInterface)service;
}
}
4. Integrated support when collections are updated
Service collections managed by Spring DM follow these rules:
■ For mandatory service collections, an empty collection throws a ServiceUnavailableException
exception when trying to use an iterator.
■ For optional service collections, an empty collection throws no exception and is simply empty.
When parsing collections, the Iterator interface must be used as in standard Java applications.
Spring DM automatically updates iterators when services disappear, to avoid dealing with the
resulting stale service references. Note that this feature has no impact on unregistered service
instances that have been obtained from an iterator. Using them will result in a
ServiceUnavailableException because they no longer exist in the service registry.
5. Programmatic service support
优点:
(1) This programmatic support can be very useful when implementing test cases or building
Spring configurations.
(2)This approach is particularly suitable for bundles that can’t use the osgi XML namespace and
must work directly with the underlying Spring DM abstractions.
5.1 Registering a service programmatically.
The dedicated abstraction for registering OSGi services is the OsgiServiceFactoryBean class
located in the org.springframework.osgi.service.exporter.support package. As this class is
directly used by the osgi XML namespace , you’ll find it has the same configuration properties
as the service tag.
Programmatically service registration configuration:
TestService testServiceBean = new TestServiceImpl();
(...)
OsgiServiceFactoryBean factoryBean = new OsgiServiceFactoryBean();
factoryBean.setBundleContext(bundleContext);
factoryBean.setTarget(testServiceBean);
factoryBean.setInterfaces(new Class[] { TestService.class });
factoryBean.setContextClassLoader(ExportContextClassLoader.UNMANAGED);
factoryBean.afterPropertiesSet();
ServiceRegistration registration = (ServiceRegistration)factory.getObject();
(...)
factoryBean.destroy();
5.2 Referencing services programmatically
For referencing services, Spring DM provides two FactoryBean implementations: the
OsgiServiceProxyFactoryBean class for referencing a single service and the
OsgiServiceCollectionProxyFactoryBean class for a collection of services. Both classes are
located in the org.springframework.osgi.service.importer.support package.
Programmatically service referencing configuration:
OsgiServiceProxyFactoryBean factoryBean = new OsgiServiceProxyFactoryBean();
factoryBean.setBundleContext(bundleContext);
factoryBean.setInterfaces(new Class[] { TestService.class });
factoryBean.setContextClassLoader(ExportContextClassLoader.CLIENT_PROVIDER);
factoryBean.afterPropertiesSet();
TestService service = (TestService)factory.getObject();
(...)
factoryBean.destroy();
5.3 ServiceReference support
Spring DM supports injecting a service’s ServiceReference instance into a bean instead of
injecting the service instance itself. Nothing special needs to be done except for injecting the
configured reference into a property of type ServiceReference. Spring DM will automatically
inject the ServiceReference instance.
You’ll notice that the injected instance corresponds to a proxy and not the target reference of
type ServiceReference. If the underlying reference is needed, you can access it using the proxy’s
getTargetServiceReference method, as shown in the followingt:
ServiceReference serviceReference = getServiceReference();
ServiceReference nativeReference =
((ServiceReferenceProxy)serviceReference).getTargetServiceReference();
Having injected the ServiceReference for the referenced service, the instance can be used within
the application, as in the first of the preceding code lines. Spring DM allows the native reference
given by the OSGi container to be accessed through the proxy via the getTargetServiceReference
method (as in the second of the code lines).
A typical use case for this technique is when you want to get hold of a real OSGi service because
an OSGi container implementation expects a native ServiceReference instance instead of a Spring
DM proxy.