The Java Service Provider Interface (SPI) libraries let you dynamically load classes with open parameter-free constructors based on the interfaces that they implement, and all this is done using META-INF/services .
First you need an interface :
package com.example; public interface SomeService { String getServiceId(); String getDisplayName(); }
Then, when you need them, you can load them using the Java ServiceLoader class, which implements Iterable :
ServiceLoader<SomeService> loader = ServiceLoader.load(SomeService.class); for (SomeService serv : loader) { System.out.println(serv.getDisplayName()); }
Then, when you have 1 or more implementing classes on your class path, they are registered with META-INF/services . So, if you have an implementation:
package com.acme; public class SomeImplementation implements SomeService {
Note that this class needs a default constructor with no arguments; this is optional.
You register it in the classloader, creating a file in META-INF/services in your classpath (for example, in the root of your jar) with the following properties:
- The file name is the fully qualified name of the interface class, in this case
com.example.SomeService - This file contains a list of implementations, separated by a newline, so for an example implementation it will contain one line:
com.acme.SomeImplementation .
And here you are. How you create your project will determine where you put the META-INF/services material. Maven, Ant, etc. Everyone has ways to handle this. I recommend asking another question about your specific build process if you have problems adding these files to your build.
source share