`

SpringDM笔记17-Handling Collections of OSGi Services

 
阅读更多

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.

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics