Assume I have one interface com.example.Marker
and I do have one implementation of this, eg com.example.MarkerImplA
. To get one of them registered, I need to place a text file in META-INF/services/com.example.Marker
looking like this
com.example.MarkerImplA
This works like a charme. Now, I have another implementation in the same jar file, eg com.example.MarkerImpl2
. How do I achieve the registration of the second one?
Just add multiple lines with the fully-qualified provider's class name
So if your SPI is com.example.Marker
META-INF/services/com.example.Marker
add each implementation in a new line
com.example.MarkerImplA
com.example.MarkerImplB
com.example.MarkerImplC
For details take a look at the JAR File Specification
Provider-Configuration File
A service provider identifies itself by placing a provider-configuration file in the resource directory META-INF/services. The file's name should consist of the fully-qualified name of the abstract service class. The file should contain a newline-separated list of unique concrete provider-class names. Space and tab characters, as well as blank lines, are ignored. The comment character is '#' (0x23); on each line all characters following the first comment character are ignored. The file must be encoded in UTF-8.
Provider lookup
Use the ServiceLoader<T>
that was introduced in Java 1.6
ServiceLoader<Marker> markerLoader = ServiceLoader.load(com.example.Marker.class);
for (Marker marker : markerLoader ) {
// select the marker you want or use all
// only for demo
System.out.println(marker);
}
Prior to 1.6 you have to implement the service loader by yourself or use a library. E.g. the apache discovery library's Service
.
A note about plug-ins
It is possible to have multiple META-INF/service
provider-configuration files in different deployment units, usually jar archives.
archive1.jar
+- META-INF/services/com.example.Marker
archive2.jar
+- META-INF/services/com.example.Marker
A lookup via the ServiceLoader<T>
will pick up all implementations in all archives. This is done using ClassLoader.getResources()
.
Thus you only have to add a jar to the classpath and the provided services can be picked up. That gives you the opportunity to build a plug-in architecture.
This is how spring works. You just add a jar to the classpath and spring features are available, because spring scans for it's service definitions. These definitions are named e.g. spring.handlers
. Spring handlers are namespace handlers that extend the xml parsing to create BeanDefinition
s that a BeanFactory
uses to create spring beans for the ApplicationContext
. See e.g. spring-tx.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With