Java SPI Vs @Autoservice
Java SPI (Service Provider Interface) is a design pattern that typically use the same interface for multiple services and has the service implement that interface.
Use case: let the user choose service of the same type they wanna use. For example:
- Database Driver
- Logging library / type, etc..
We can use ServiceLoader
to load the correct service.
For example:
// Core module
public interface MyService {
void doSomething();
}
// Implementation module 1
public class MyServiceImpl1 implements MyService {
@Override
public void doSomething() {
// Implementation 1
}
}
// Implementation module 2
public class MyServiceImpl2 implements MyService {
@Override
public void doSomething() {
// Implementation 2
}
}
// META-INF/services/com.example.MyService
// Contains:
// com.example.MyServiceImpl1
// com.example.MyServiceImpl2
// Application code
ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);
for (MyService service : serviceLoader) {
service.doSomething(); // Dynamically uses implementations
}
Note: for this to work, we have to manually create the META-INF
for our service configuration which contains the package for our services.
@AutoService
Google @AutoService
aim to help us with the configuration creation which will automatically create the services for us:
annotationProcessor 'com.google.auto.service:auto-service:1.1.1'
implementation 'com.google.auto.service:auto-service:1.1.1'
In the code we can then just do
// Core module
public interface MyService {
void doSomething();
}
// Implementation module 1
@AutoService(MyService.class)
public class MyServiceImpl1 implements MyService {
@Override
public void doSomething() {
// Implementation 1
}
}
// Implementation module 2
@AutoService(MyService.class)
public class MyServiceImpl2 implements MyService {
@Override
public void doSomething() {
// Implementation 2
}
}
// Application code
ServiceLoader<MyService> serviceLoader = ServiceLoader.load(MyService.class);
for (MyService service : serviceLoader) {
service.doSomething(); // Dynamically uses implementations
}
@AutoService
will automatically create the META-INF for us and put it inside the build/
folder