Share via


ServiceLoader Class

Definition

A facility to load implementations of a service.

[Android.Runtime.Register("java/util/ServiceLoader", DoNotGenerateAcw=true)]
[Java.Interop.JavaTypeParameters(new System.String[] { "S" })]
public sealed class ServiceLoader : Java.Lang.Object, IDisposable, Java.Interop.IJavaPeerable, Java.Lang.IIterable
[<Android.Runtime.Register("java/util/ServiceLoader", DoNotGenerateAcw=true)>]
[<Java.Interop.JavaTypeParameters(new System.String[] { "S" })>]
type ServiceLoader = class
    inherit Object
    interface IIterable
    interface IJavaObject
    interface IDisposable
    interface IJavaPeerable
Inheritance
ServiceLoader
Attributes
Implements

Remarks

A facility to load implementations of a service.

A service is a well-known interface or class for which zero, one, or many service providers exist. A service provider (or just provider) is a class that implements or subclasses the well-known interface or class. A ServiceLoader is an object that locates and loads service providers deployed in the run time environment at a time of an application's choosing. Application code refers only to the service, not to service providers, and is assumed to be capable of choosing between multiple service providers (based on the functionality they expose through the service), and handling the possibility that no service providers are located.

<h2> Obtaining a service loader </h2>

An application obtains a service loader for a given service by invoking one of the static load methods of ServiceLoader. <!--If the application is a module, then its module declaration must have a uses directive that specifies the service; this helps to locate providers and ensure they will execute reliably. In addition, if the application module does not contain the service, then its module declaration must have a requires directive that specifies the module which exports the service. It is strongly recommended that the application module does <b>not</b> require modules which contain providers of the service.--/>

A service loader can be used to locate and instantiate providers of the service by means of the #iterator() iterator method. ServiceLoader also defines the #stream() stream method to obtain a stream of providers that can be inspected and filtered without instantiating them.

As an example, suppose the service is com.example.CodecFactory, an interface that defines methods for producing encoders and decoders:

{@code
                package com.example;
                public interface CodecFactory {
                    Encoder getEncoder(String encodingName);
                    Decoder getDecoder(String encodingName);
                }
            }

The following code obtains a service loader for the CodecFactory service, then uses its iterator (created automatically by the enhanced-for loop) to yield instances of the service providers that are located:

{@code
                ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
                for (CodecFactory factory : loader) {
                    Encoder enc = factory.getEncoder("PNG");
                    if (enc != null)
                        ... use enc to encode a PNG file
                        break;
                    }
            }

Sometimes an application may wish to inspect a service provider before instantiating it, in order to determine if an instance of that service provider would be useful. For example, a service provider for CodecFactory that is capable of producing a "PNG" encoder may be annotated with @PNG. The following code uses service loader's stream method to yield instances of Provider<CodecFactory> in contrast to how the iterator yields instances of CodecFactory:

{@code
                ServiceLoader<CodecFactory> loader = ServiceLoader.load(CodecFactory.class);
                Set<CodecFactory> pngFactories = loader
                       .stream()                                              // Note a below
                       .filter(p -> p.type().isAnnotationPresent(PNG.class))  // Note b
                       .map(Provider::get)                                    // Note c
                       .collect(Collectors.toSet());
            }

<ol type="a"> <li> A stream of Provider<CodecFactory> objects </li> <li> p.type() yields a Class<CodecFactory></li> <li> get() yields an instance of CodecFactory</li> </ol>

<h2> Designing services </h2>

A service is a single type, usually an interface or abstract class. A concrete class can be used, but this is not recommended. The type may have any accessibility. The methods of a service are highly domain-specific, so this API specification cannot give concrete advice about their form or function. However, there are two general guidelines: <ol> <li>

A service should declare as many methods as needed to allow service providers to communicate their domain-specific properties and other quality-of-implementation factors. An application which obtains a service loader for the service may then invoke these methods on each instance of a service provider, in order to choose the best provider for the application.

</li> <li>

A service should express whether its service providers are intended to be direct implementations of the service or to be an indirection mechanism such as a "proxy" or a "factory". Service providers tend to be indirection mechanisms when domain-specific objects are relatively expensive to instantiate; in this case, the service should be designed so that service providers are abstractions which create the "real" implementation on demand. For example, the CodecFactory service expresses through its name that its service providers are factories for codecs, rather than codecs themselves, because it may be expensive or complicated to produce certain codecs.

</li> </ol>

<h2> "developing-service-providers">Developing service providers</h2>

A service provider is a single type, usually a concrete class. An interface or abstract class is permitted because it may declare a static provider method, discussed later. The type must be public and must not be an inner class.

A service provider and its supporting code may be developed in a module, which is then deployed on the application module path or in a modular image. Alternatively, a service provider and its supporting code may be packaged as a JAR file and deployed on the application class path. The advantage of developing a service provider in a module is that the provider can be fully encapsulated to hide all details of its implementation.

An application that obtains a service loader for a given service is indifferent to whether providers of the service are deployed in modules or packaged as JAR files. The application instantiates service providers via the service loader's iterator, or via Provider Provider objects in the service loader's stream, without knowledge of the service providers' locations.

<h2> Deploying service providers on the class path </h2>

A service provider that is packaged as a JAR file for the class path is identified by placing a provider-configuration file in the resource directory META-INF/services. The name of the provider-configuration file is the fully qualified binary name of the service. The provider-configuration file contains a list of fully qualified binary names of service providers, one per line.

For example, suppose the service provider com.example.impl.StandardCodecs is packaged in a JAR file for the class path. The JAR file will contain a provider-configuration file named:

<blockquote>META-INF/services/com.example.CodecFactory</blockquote>

that contains the line:

<blockquote>com.example.impl.StandardCodecs # Standard codecs</blockquote>

"format">The provider-configuration file must be encoded in UTF-8. Space and tab characters surrounding each service provider's name, as well as blank lines, are ignored. The comment character is '#' (U+0023<span style="font-size:smaller;">NUMBER SIGN</span>); on each line all characters following the first comment character are ignored. If a service provider class name is listed more than once in a provider-configuration file then the duplicate is ignored. If a service provider class is named in more than one configuration file then the duplicate is ignored.

A service provider that is mentioned in a provider-configuration file may be located in the same JAR file as the provider-configuration file or in a different JAR file. The service provider must be visible from the class loader that is initially queried to locate the provider-configuration file; this is not necessarily the class loader which ultimately locates the provider-configuration file.

<h2> Timing of provider discovery </h2>

Service providers are loaded and instantiated lazily, that is, on demand. A service loader maintains a cache of the providers that have been loaded so far. Each invocation of the iterator method returns an Iterator that first yields all of the elements cached from previous iteration, in instantiation order, and then lazily locates and instantiates any remaining providers, adding each one to the cache in turn. Similarly, each invocation of the stream method returns a Stream that first processes all providers loaded by previous stream operations, in load order, and then lazily locates any remaining providers. Caches are cleared via the #reload reload method.

<h2> "errors">Errors</h2>

When using the service loader's iterator, the Iterator#hasNext() hasNext and Iterator#next() next methods will fail with ServiceConfigurationError if an error occurs locating, loading or instantiating a service provider. When processing the service loader's stream then ServiceConfigurationError may be thrown by any method that causes a service provider to be located or loaded.

When loading or instantiating a service provider in a module, ServiceConfigurationError can be thrown for the following reasons:

When reading a provider-configuration file, or loading or instantiating a provider class named in a provider-configuration file, then ServiceConfigurationError can be thrown for the following reasons:

<ul>

<li> The format of the provider-configuration file violates the format specified above; </li>

<li> An IOException IOException occurs while reading the provider-configuration file; </li>

<li> A service provider cannot be loaded; </li>

<li> A service provider is not assignable to the service's interface or class, or does not define a provider constructor, or cannot be instantiated. </li>

</ul>

<h2> Concurrency </h2>

Instances of this class are not safe for use by multiple concurrent threads.

<h3> Null handling </h3>

Unless otherwise specified, passing a null argument to any method in this class will cause a NullPointerException to be thrown.

Added in 1.6.

Java documentation for java.util.ServiceLoader.

Portions of this page are modifications based on work created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

Properties

Class

Returns the runtime class of this Object.

(Inherited from Object)
Handle

The handle to the underlying Android instance.

(Inherited from Object)
JniIdentityHashCode (Inherited from Object)
JniPeerMembers
PeerReference (Inherited from Object)
ThresholdClass

This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.

(Inherited from Object)
ThresholdType

This API supports the Mono for Android infrastructure and is not intended to be used directly from your code.

(Inherited from Object)

Methods

Clone()

Creates and returns a copy of this object.

(Inherited from Object)
Dispose() (Inherited from Object)
Dispose(Boolean) (Inherited from Object)
Equals(Object)

Indicates whether some other object is "equal to" this one.

(Inherited from Object)
FindFirst()

Load the first available service provider of this loader's service.

GetHashCode()

Returns a hash code value for the object.

(Inherited from Object)
Iterator()

Lazily loads the available providers of this loader's service.

JavaFinalize()

Called by the garbage collector on an object when garbage collection determines that there are no more references to the object.

(Inherited from Object)
Load(Class, ClassLoader)

Creates a new service loader for the given service type and class loader.

Load(Class)

Creates a new service loader for the given service type, using the current thread's java.

LoadInstalled(Class)

Creates a new service loader for the given service type, using the extension class loader.

Notify()

Wakes up a single thread that is waiting on this object's monitor.

(Inherited from Object)
NotifyAll()

Wakes up all threads that are waiting on this object's monitor.

(Inherited from Object)
Reload()

Clear this loader's provider cache so that all providers will be reloaded.

SetHandle(IntPtr, JniHandleOwnership)

Sets the Handle property.

(Inherited from Object)
ToArray<T>() (Inherited from Object)
ToString()

Returns a string representation of the object.

(Inherited from Object)
UnregisterFromRuntime() (Inherited from Object)
Wait()

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>.

(Inherited from Object)
Wait(Int64, Int32)

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed.

(Inherited from Object)
Wait(Int64)

Causes the current thread to wait until it is awakened, typically by being <em>notified</em> or <em>interrupted</em>, or until a certain amount of real time has elapsed.

(Inherited from Object)

Explicit Interface Implementations

IJavaPeerable.Disposed() (Inherited from Object)
IJavaPeerable.DisposeUnlessReferenced() (Inherited from Object)
IJavaPeerable.Finalized() (Inherited from Object)
IJavaPeerable.JniManagedPeerState (Inherited from Object)
IJavaPeerable.SetJniIdentityHashCode(Int32) (Inherited from Object)
IJavaPeerable.SetJniManagedPeerState(JniManagedPeerStates) (Inherited from Object)
IJavaPeerable.SetPeerReference(JniObjectReference) (Inherited from Object)

Extension Methods

JavaCast<TResult>(IJavaObject)

Performs an Android runtime-checked type conversion.

JavaCast<TResult>(IJavaObject)
GetJniTypeName(IJavaPeerable)

Gets the JNI name of the type of the instance self.

JavaAs<TResult>(IJavaPeerable)

Try to coerce self to type TResult, checking that the coercion is valid on the Java side.

TryJavaCast<TResult>(IJavaPeerable, TResult)

Try to coerce self to type TResult, checking that the coercion is valid on the Java side.

ToEnumerable(IIterable)
ToEnumerable<T>(IIterable)

Applies to