First of all, what is the Java SPI?

SPI (Service Provider Interface) is a built-in Service discovery mechanism in JDK.

Why is SPI needed?

Our modern system more and more big, if there is something wrong with the design and architecture, is likely to be extremely important, we recommend based on interface in object-oriented programming, based on the interface between module programming, so it is obvious that the benefits of the code or hard coding, different implementer shall, in accordance with the interface specification to realize its own internal operations, Then, the corresponding service provider’s service implementation is obtained according to the SPI specification during use. Registering and discovering services through the SPI service loading mechanism effectively prevents the service provider from being written to death in code. So it can realize decoupling between modules based on interface programming.

SPI mechanism conventions:

1. In the meta-INF /services/ directory, create a file named with the fully qualified name of the interface. The content of the file is the fully qualified name of the API implementation class

2. Use the ServiceLoader class to dynamically load the meta-INF implementation class

3. If the SPI implementation class is Jar, it needs to be placed in the main program ClassPath

4. The API concrete implementation class must have a constructor that takes no arguments

As shown in figure:


Cases that have been used now:

  • Common-logging A facade interface for logging originally provided by Apache. Only interface, no implementation. Specific party sponsored by the provider implementation, found by scanning META – log provider is INF/services/org.apache.com mons. Logging. LogFactory configuration files, by reading the article content Find a log business implementation class. As long as we include this file in our logging implementation, and specify the LogFactory factory interface implementation class in the file.
  • Before JDBC JDBC 4.0, developers also needed to load drivers based on class.forname (” XXX “). Create a Connection: DriverManage getConnection (), a Connection con = aDriver. Driver. Connect (url, info); Driver member variables, java.sql.Driver interface, Java public a loading driver interface, Java is not implemented, as for the implementation of this interface by various Jdbc vendors to implement. Such as MySQL, The mysql-connector-java-5.1.38.jar meta-inf. Services package contains a java.sql.Driver file with two lines com.mysql.jdbc.driver com.mysql.fabric.jdbc.FabricMySQLDriver

The sample Demo:

  1. Creating a Maven project
  2. The directory is as follows:

      


  3. OrderService code. Java

    package com.demo.spi.service;
    
    public interface OrderService {
        int getOrderCountById(int id);
    }
    Copy the code

      CustomerOrderServiceImpl.java

package com.demo.spi.impl;

import com.demo.spi.service.OrderService;

public class CustomerOrderServiceImpl implements OrderService {

    public int getOrderCountById(int id) {
        System.out.println("cutomer order count is 10");
        return10; }}Copy the code

       AgencyOrderServiceImpl.java

package com.demo.spi.impl;

import com.demo.spi.service.OrderService;

public class AgencyOrderServiceImpl implements OrderService {

    public int getOrderCountById(int id) {
        System.out.println("agency order count is 20");
        return20; }}Copy the code

Under the meta-inf filename: com. Demo. Spi. Service. The OrderService, content of the file:

com.demo.spi.impl.AgencyOrderServiceImpl
com.demo.spi.impl.CustomerOrderServiceImplCopy the code

4. Create a test project Java Project




Code making address: https://github.com/HuoMoreMore/demo-spi

Before running the main method we need to package the first project jar dependency into the second Java project. When we’re done, click Run and you can see the output printed from our two serviceImpl methods in project 1. This means that the ServiceLoader dynamically finds the implementation classes in project 1 through the jar configuration and stores them in memory, so we can directly call the two implementation classes provided in Project 1 and output them correctly.

If you need to know the ServiceLoader source code, please refer to:

https://www.jianshu.com/p/a6073e9f8cb4