What is a service?
A service is represented by a single type, that is, a single interface or an abstract class. A service provider is a specific implementation of a service. The question is how do we let the service loader know the provider's implementation so that it can instantiate and cache it.
Identifying service provider
A service provider is identified by placing a provider-configuration file in META-INF/services. The file's name is the fully-qualified class name of the service's type. The file contains a list of fully-qualified binary names of concrete provider classes, one per line.
Suppose the service is java.sql.Driver and the implementations are DriverOne, DriverTwo and DriverThree
where DriverOne and DriverTwo belong to one provider and DriverThree belongs to another provider.
We need two configuration files located in different directories. The configuration file will be called by the fully-qualified name of the service, in our case, it will be java.sql.Driver.
![]() |
Service Loader |
Contents of provider1/META-INF/services/java.sql.Driver
drivers.DriverOne#This is driver one #Next is driver two drivers.DriverTwo
Contents of provider2/META-INF/services/java.sql.Driver
drivers.DriverThree
Services resources
The next step would be to make the classloader load the configuration files. First priority would be let the thread context's class loader load the resources. If there is no classloader stashed at thread's context, it will be delegated to system's class loader. Read more about the hierarchy of classloaders here.In our example, we add directories provider1 and provider2 to the classpath so that the classloader can locate these resources.
There is already one java.sql.Driver configuration file in jdk1.7.0_11/jre/lib/resources.jar so the classloader ends up locating three configuration files.
![]() |
Service Loader |
Loading services
When we call ServiceLoader.load(Driver.class), it creates a cache for providers and an iterator which will lazily instantiate the Driver implementations as we iterate through the resources.
![]() |
Iterating through services
As we iterate through each resource, the configuration file will be read. Each line in the configuration file will have one fully-qualified class name which will be used to load and instantiate. The instantiated provider class will be cached for future iterations.![]() |
Service Loader |
No comments:
Post a Comment