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 directoryMETA-INF/services/directory
  • inMETA-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
  • throughServiceLoader.loadMethod 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