Java ServiceLoader Explained
The ServiceLoader is a simple and best way to use built-in mechanism for dynamic loading of interface implementations. With the service loader — providing means for instantiation (but not the wiring) — a simple dependency injection mechanism can be built in Java SE. With the ServiceLoader interface and implementation separation becomes natural and programs can be conveniently extended.
If you take a closer look most of the Java API are implemented based on the ServiceLoader
The class java.util.ServiceLoader
is based of the design pattern SPI (Service Provider Interface) pattern.SPI is an API intended to be implemented or extended by plugins/modules.
Let’s understand that with an example.
Java 6 has introduced a feature for discovering and loading implementations matching a given interface: Service Provider Interface (SPI).
In this tutorial, we’ll create the components of Java SPI and show how we can apply it to a real-time implementation.
Assume we are designing an application framework . We want Framework to be extensible. We will create API interfaces/classes visible to outside world and typically called Services to describe what framework does. A particular application will call the API to achieve a goal. A set of same interfaces/classes (SPI) of the framework are treated as extension points by plugins and modules. These plugins/modules/dependency are typically called Service Provider. They either provide concrete implementation or extend those interfaces/classes of the framework to provide functionality.
Application will be dependent on a framework to get a service provider. Framework will look for the provider to get the service, this is run time. So the provider will have the implementation of the framework interface. Framework will expose an interface which provider can implement. Now let us go to a code example
Here we create three dependency projects. Create a framework project and two provider project as explained in the diagram above
Create a project named framework, and add an interface in this project
package com.escuela.service;
/**
*
*/
public interface EscuelaService {
/**
*
* @return
*/
String sayHello();
}
Create a project named provider, for this project framework is a dependency.
Then create a Java class which implement the interface created above
package com.escuela.impl;
import com.escuela.service.EscuelaService;
public class EscuelaServiceImpl implements EscuelaService {
public String sayHello() {
return "Good Morning from Escuela";
}
}
in the resource of this project you need create a folder hierarchy META-INF/service, then create a file named as com.escuela.service.EscuelaService. We are defining a service implementation in the provider package.
In this file add the content below. Here we are giving full qualified name of the implementation class and package it as a jar.
com.escuela.impl.EscuelaServiceImpl
Let’s create one more project which is the application. For this project you have two dependencies framework and provider. Hope this clear. If you are creating a maven based project you will add these as dependencies. In simple words both are libraries
package com.escuela.start;
import com.escuela.service.EscuelaService;
import java.util.ServiceLoader;
public class AppStart {
/**
*
* @param args
*/
public static void main(String[] args) {
EscuelaService service=getDefault();
System.out.println(service.sayHello());
}
/**
*
* @return
*/
public static EscuelaService getDefault() {
// load our plugin
ServiceLoader<EscuelaService> serviceLoader =ServiceLoader.load(EscuelaService.class);
for (EscuelaService provider : serviceLoader) {
return provider;
}
throw new NoClassDefFoundError("Unable to load a driver "+EscuelaService.class.getName());
}
}
Now got ahead an run the application code. You will see the output as
"Good Morning from Escuela"
Hit the clap button if you like this article .. which means a lot to us !!