Class DiscoverSingleton
Discover singleton service providers. This
DiscoverSingleton instances are cached by the Discovery service, keyed by a combination of
- thread context class loader,
- groupContext, and
- SPI.
In the context of this package, a service interface is defined by a Service Provider Interface (SPI). The SPI is expressed as a Java interface, abstract class, or (base) class that defines an expected programming interface.
DiscoverSingleton provides the find
methods for locating and
instantiating a singleton instance of an implementation of a service (SPI).
Each form of find
varies slightly, but they all perform the
same basic function.
The simplest find
methods are intended for direct use by
components looking for a service. If you are not sure which finder(s)
to use, you can narrow your search to one of these:
- static <T> T find(Class<T> spi);
- static <T> T find(Class<T> spi, Properties properties);
- static <T> T find(Class<T> spi, String defaultImpl);
- static <T> T find(Class<T> spi, Properties properties, String defaultImpl);
- static <T> T find(Class<T> spi, String propertiesFileName, String defaultImpl);
- static <T> T find(ClassLoaders loaders, SPInterface<T> spi, PropertiesHolder holder, DefaultClassHolder<T> holder);
DiscoverSingleton.find
methods proceed as follows:
- Examine an internal cache to determine if the desired service was previously identified and instantiated. If found in cache, return it.
-
Get the name of an implementation class. The name is the first
non-null value obtained from the following resources:
-
The value of the (scoped) system property whose name is the same as
the SPI's fully qualified class name (as given by SPI.class.getName()).
The
ScopedProperties
class provides a way to bind properties by classloader, in a secure hierarchy similar in concept to the way classloader find class and resource files. SeeScopedProperties
for more details.If the ScopedProperties are not set by users, then behaviour is equivalent to
System.getProperty()
. -
The value of a
Properties properties
property, if provided as a parameter, whose name is the same as the SPI's fully qualifed class name (as given by SPI.class.getName()). -
The value obtained using the JDK1.3+ 'Service Provider' specification
(http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html) to locate a
service named
SPI.class.getName()
. This is implemented internally, so there is not a dependency on JDK 1.3+.
-
The value of the (scoped) system property whose name is the same as
the SPI's fully qualified class name (as given by SPI.class.getName()).
The
-
If the name of the implementation class is non-null, load that class.
The class loaded is the first class loaded by the following sequence
of class loaders:
- Thread Context Class Loader
- DiscoverSingleton's Caller's Class Loader
- SPI's Class Loader
- DiscoverSingleton's (this class or wrapper) Class Loader
- System Class Loader
-
If the name of the implementation class is null, AND the default
implementation class (
defaultImpl
) is null, then an exception is thrown. -
If the name of the implementation class is null, AND the default
implementation class (
defaultImpl
) is non-null, then load the default implementation class. The class loaded is the first class loaded by the following sequence of class loaders:- SPI's Class Loader
- DiscoverSingleton's (this class or wrapper) Class Loader
- System Class Loader
This limits the scope in which the default class loader can be found to the SPI, DiscoverSingleton, and System class loaders. The assumption here is that the default implementation is closely associated with the SPI or system, and is not defined in the user's application space.
An exception is thrown if the class cannot be loaded.
- Verify that the loaded class implements the SPI: an exception is thrown if the loaded class does not implement the SPI.
- Create an instance of the class.
Variances for various forms of the find
methods are discussed with each such method.
Variances include the following concepts:
- rootFinderClass - a wrapper encapsulating a finder method (factory or other helper class). The root finder class is used to determine the 'real' caller, and hence the caller's class loader - thereby preserving knowledge that is relevant to finding the correct/expected implementation class.
- propertiesFileName -
Properties
may be specified directly, or by property file name. A property file is loaded using the same sequence of class loaders used to load the SPI implementation:- Thread Context Class Loader
- DiscoverSingleton's Caller's Class Loader
- SPI's Class Loader
- DiscoverSingleton's (this class) Class Loader
- System Class Loader
- groupContext - differentiates service providers for different
logical groups of service users, that might otherwise be forced to share
a common service and, more importantly, a common configuration of that
service.
The groupContext is used to qualify the name of the property file name:
groupContext + '.' + propertiesFileName
. If that file is not found, then the unqualified propertyFileName is used.In addition, groupContext is used to qualify the name of the system property used to find the service implementation by prepending the value of
groupContext
to the property name:groupContext> + '.' + SPI.class.getName()
. Again, if a system property cannot be found by that name, then the unqualified property name is used.
IMPLEMENTATION NOTE - This implementation is modelled after the SAXParserFactory and DocumentBuilderFactory implementations (corresponding to the JAXP pluggability APIs) found in Apache Xerces.
- Version:
- $Revision: 1089242 $ $Date: 2011-04-05 23:33:21 +0200 (Tue, 05 Apr 2011) $
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic <T> T
Find implementation of SPI.static <T> T
Find implementation of SPI.static <T> T
Find implementation of SPI.static <T> T
find
(Class<T> spiClass, Properties properties) Find implementation of SPI.static <T> T
find
(Class<T> spiClass, Properties properties, String defaultImpl) Find implementation of SPI.static <T> T
find
(ClassLoaders loaders, SPInterface<T> spi, PropertiesHolder properties, DefaultClassHolder<T> defaultImpl) Find implementation of SPI.static void
release()
Release all internal references to previously created service instances associated with the current thread context class loader.static void
Release any internal references to a previously created service instance associated with the current thread context class loader.
-
Constructor Details
-
DiscoverSingleton
public DiscoverSingleton()
-
-
Method Details
-
find
Find implementation of SPI.- Type Parameters:
T
- Service Provider Interface type.- Parameters:
spiClass
- Service Provider Interface Class.- Returns:
- Instance of a class implementing the SPI.
- Throws:
DiscoveryException
- Thrown if the name of a class implementing the SPI cannot be found, if the class cannot be loaded and instantiated, or if the resulting class does not implement (or extend) the SPI.
-
find
Find implementation of SPI.- Type Parameters:
T
- Service Provider Interface type- Parameters:
spiClass
- Service Provider Interface Class.properties
- Used to determine name of SPI implementation, and passed to implementation.init() method if implementation implements Service interface.- Returns:
- Instance of a class implementing the SPI.
- Throws:
DiscoveryException
- Thrown if the name of a class implementing the SPI cannot be found, if the class cannot be loaded and instantiated, or if the resulting class does not implement (or extend) the SPI.
-
find
Find implementation of SPI.- Type Parameters:
T
- Service Provider Interface type- Parameters:
spiClass
- Service Provider Interface Class.defaultImpl
- Default implementation.- Returns:
- Instance of a class implementing the SPI.
- Throws:
DiscoveryException
- Thrown if the name of a class implementing the SPI cannot be found, if the class cannot be loaded and instantiated, or if the resulting class does not implement (or extend) the SPI.
-
find
public static <T> T find(Class<T> spiClass, Properties properties, String defaultImpl) throws DiscoveryException Find implementation of SPI.- Type Parameters:
T
- Service Provider Interface type- Parameters:
spiClass
- Service Provider Interface Class.properties
- Used to determine name of SPI implementation, and passed to implementation.init() method if implementation implements Service interface.defaultImpl
- Default implementation.- Returns:
- Instance of a class implementing the SPI.
- Throws:
DiscoveryException
- Thrown if the name of a class implementing the SPI cannot be found, if the class cannot be loaded and instantiated, or if the resulting class does not implement (or extend) the SPI.
-
find
public static <T> T find(Class<T> spiClass, String propertiesFileName, String defaultImpl) throws DiscoveryException Find implementation of SPI.- Type Parameters:
T
- Service Provider Interface type- Parameters:
spiClass
- Service Provider Interface Class.propertiesFileName
- Used to determine name of SPI implementation, and passed to implementation.init() method if implementation implements Service interface.defaultImpl
- Default implementation.- Returns:
- Instance of a class implementing the SPI.
- Throws:
DiscoveryException
- Thrown if the name of a class implementing the SPI cannot be found, if the class cannot be loaded and instantiated, or if the resulting class does not implement (or extend) the SPI.
-
find
public static <T> T find(ClassLoaders loaders, SPInterface<T> spi, PropertiesHolder properties, DefaultClassHolder<T> defaultImpl) throws DiscoveryException Find implementation of SPI.- Type Parameters:
T
- Service Provider Interface type- Parameters:
loaders
- TheClassLoader
holderspi
- Service Provider Interface Class.properties
- Used to determine name of SPI implementation, and passed to implementation.init() method if implementation implements Service interface.defaultImpl
- Default implementation.- Returns:
- Instance of a class implementing the SPI.
- Throws:
DiscoveryException
- Thrown if the name of a class implementing the SPI cannot be found, if the class cannot be loaded and instantiated, or if the resulting class does not implement (or extend) the SPI.
-
release
Release all internal references to previously created service instances associated with the current thread context class loader. Therelease()
method is called for service instances that implement theService
interface. This is useful in environments like servlet containers, which implement application reloading by throwing away a ClassLoader. Dangling references to objects in that class loader would prevent garbage collection. -
release
Release any internal references to a previously created service instance associated with the current thread context class loader. If the SPI instance implementsService
, then callrelease()
.- Parameters:
spiClass
- The previously created service
-