Simple Java Service Provider Platform?

I mean the "service provider infrastructure" as discussed in Chapter 2 of Effective Java , which seems to be the right way to handle the problem that I encounter when I need to instantiate one of several classes at runtime, based on String to select this service, and a Configuration object (essentially an XML snippet):

But how can I get individual service providers (for example, a bunch of default providers + some custom providers) to register?

  interface FooAlgorithm { /* methods particular to this class of algorithms */ } interface FooAlgorithmProvider { public FooAlgorithm getAlgorithm(Configuration c); } class FooAlgorithmRegistry { private FooAlgorithmRegistry() {} static private final Map<String, FooAlgorithmProvider> directory = new HashMap<String, FooAlgorithmProvider>(); static public FooAlgorithmProvider getProvider(String name) { return directory.get(serviceName); } static public boolean registerProvider(String name, FooAlgorithmProvider provider) { if (directory.containsKey(name)) return false; directory.put(name, provider); return true; } } 

eg. if I write custom classes MyFooAlgorithm and MyFooAlgorithmProvider to implement FooAlgorithm and I distribute them in the bank, is there any way to get the registerProvider automatically call or my client programs that use the algorithm should explicitly call FooAlgorithmRegistry.registerProvider () for each class they want use?

+5
source share
2 answers

I think you need to create META-INF / services / full.qualified.ClassName and list things there, but I don't remember the spec ( JAR file specification or this ).

The practical descriptions of the API design in Chapter 8 of the Java Archive Book are dedicated to SPI.

ServiceLoader can help you list the available implementations. For example, with the PersistenceProvider interface:

 ServiceLoader<PersistenceProvider> loader = ServiceLoader.load(PersistenceProvider.class); Iterator<PersistenceProvider> implementations = loader.iterator(); while(implementations.hasNext()) { PersistenceProvider implementation = implementations.next(); logger.info("PersistenceProvider implementation: " + implementation); } 
+10
source

You may have a JAR client registered by providers in a static initializer block within a certain class, which, as you know, will be called before FooAlgorithmRegistry.getProvider() , something like:

 static { FooAlgorithmRegistry.registerProvider("test", new MyFooAlgorithmProvider()); } 

But it can be quite difficult to find a way to guarantee that this will execute (static initializers are guaranteed to run once and only once when the class is first loaded) before the factory access method.

0
source

All Articles