This is the second day of my participation in the Java Development Kit (JDK) SPI mechanism, as well as related source code examples
1. What is the JDK SPI mechanism
- Create it in the project’s resource files directory
META-INF/services/
directory - in
META-INF/services/
Create a file whose name is the qualified name of the interfacecom.m.code.HelloService
- Line the qualified name of the implementation class in a file with the qualified name of the interface, as in:
com.m.code.service.impl.HelloServiceImpl
com.m.code.service.impl.SimpleHelloServiceImpl
Copy the code
- through
ServiceLoader.load
Method loads the implementation class for the specified interface
2. Source code analysis
The main core class is java.util.Serviceloader
- You can see the loaded directory in the class
private static final String PREFIX = "META-INF/services/";
Copy the code
- Call the load method
public static <S> ServiceLoader<S> load(Class service, ClassLoader loader)
{
return new ServiceLoader<>(service, loader);
}
Copy the code
- The ServiceLoader constructor is actually called
private ServiceLoader(Class<S> svc, ClassLoader cl) {
service = Objects.requireNonNull(svc, "Service interface cannot be null");
loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
acc = (System.getSecurityManager() != null)? AccessController.getContext() :null;
reload();
}
Copy the code
- Core method
private S nextService(a) {
// Check if there is any service left
if(! hasNextService())throw new NoSuchElementException();
String cn = nextName;
nextName = null; Class<? > c =null;
try {
/ / create the Class
c = Class.forName(cn, false, loader);
} catch (ClassNotFoundException x) {
fail(service,
"Provider " + cn + " not found");
}
// This verifies whether it is the implementation class of the interface
if(! service.isAssignableFrom(c)) { fail(service,"Provider " + cn + " not a subtype");
}
try {
// reflection creates objects
S p = service.cast(c.newInstance());
providers.put(cn, p);
return p;
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated",
x);
}
throw new Error(); // This cannot happen
}
Copy the code
Practice 3.
3.1 Creating interface HelloService
/** * HelloService interface */
public interface HelloService {
void say(a);
}
Copy the code
3.2 Create an implementation class for interface HelloService
/** * HelloService interface implementation class */
public class HelloServiceImpl implements HelloService {
@Override
public void say(a) {
System.out.println("Hello!!!"); }}Copy the code
/** * HelloService interface implementation class * simple implementation */
public class SimpleHelloServiceImpl implements HelloService {
@Override
public void say(a) {
System.out.println("simple Hello!"); }}Copy the code
3.3 Add resources under the projectMETA-INF/services/
directory
And under the directory to create a name for the interface of the qualified name file. Com m.c. The ode service. HelloService
3.4 Enter the qualified name of the interface implementation class of the corresponding interface in the file
com.m.code.service.impl.HelloServiceImpl
com.m.code.service.impl.SimpleHelloServiceImpl
Copy the code
3.5 Test in methods
/** * HelloService test * test JDK SPI */
public class Main {
public static void main(String[] args) {
// Install the HelloService implementation class with the ServiceLoader
ServiceLoader<HelloService> serviceLoader = ServiceLoader.load(HelloService.class);
// Print the result
for(HelloService next : serviceLoader) { next.say(); }}}Copy the code