What is the SPI

SPI, short for Service Provider Interface, is a mechanism provided by the JDK by default to separate interfaces from implementation classes. This mechanism can decouple the interface and implementation, greatly improving the scalability of the system.

SPI convention: When a Jar package needs to provide an implementation class for an interface, the Jar package needs to create a file named after the service interface in the meta-INF /services/ directory. This file contains the concrete implementation class that implements the service interface. When an external application assembs the module, it can find the implementation class name in the meta-INF /services/ Jar file and load the instantiation to complete the module injection.

As shown in the following example, the JCL-over-SLf4J Jar package provides an implementation of the LogFactory interface in Conmon-logging.

The contents of the file are as follows:

The JDK also provides a utility class: java.util.Serviceloader to make it easier to find the implementation of the service.

The ServiceLoader in the code above traverses all LogFactory implementations provided using the SPI mechanism.

Application scenarios

The main applications of the SPI mechanism are framework extensions and component replacements, for example

  • Runtime loading of JDBC interface classes: We need to add Jar dependencies to connect to specific databases, but we do not need to do any additional configuration, just put the Jar package in the classpath. This is one of the most common application scenarios for SPI.
  • Logging facade loads specific logging implementation classes: as mentioned in previous blogs, JCL and SLF4J are just logging implementation classes, while Log4j and LOgBack are concrete logging implementations. JCL and SLF4J also use the SPI mechanism when loading logging implementation classes, as illustrated in the section above.
  • Spring in the extensive use of the SPI: such as implementation of ServletContainerInitializer servlet3.0 specification, automatic Type Conversion Type Conversion SPI (Converter SPI, the Formatter SPI), etc

Their implementation#

Let’s take a step-by-step look at how the SPI mechanism can be used, from defining interfaces to providing SPI implementation classes.

Step1: define an interface first

Copy `public interface SaySomething { String say(String name); } `

Step2: write the implementation class

Copy `public class ASaySomething implements SaySomething { @Override public String say(String name) { return "Hi,"+name+", l am A..." ; }} `

Step3: add the meta-info /services directory under resource. After adding this directory, add a file with the fully qualified name of the SaySomething interface. This file contains the specific implementation class you want to set up. So we’re going to set the implementation class up here to be ASaySomething.

Step4: use the SPI mechanism

Copy `public static void main(String[] args) { ServiceLoader loader = ServiceLoader.load(SaySomething.class); loader.forEach(item ->{item.say("csx"); }); } `

API and SPI comparison#

The term API is often used in development, but here’s a summary of the differences:

  • Application Programming Interfaces (apis) In most cases, the implementer formulates the Interface and implements the Interface. The caller only relies on the Interface invocation and does not have the right to choose different implementations. In terms of users, apis are used directly by application developers.

  • The Service Provider Interface (SPI) allows the caller to formulate the Interface specification and provide it to the external for implementation. The caller selects the required external implementation during invocation. In terms of users, SPI is used by framework extenders.

The advantages and disadvantages#

advantages

  • The advantage of using the Java SPI mechanism is decoupling, so that the assembly control logic of a third-party service module is separated from, rather than coupled to, the caller’s business code. Applications can enable framework extensions or replace framework components depending on the business situation

disadvantages

  • SPI must iterate through all the implementation classes of the interface before finally choosing which class to use. Some unwanted classes will also be instantiated, which can be a waste of memory.
  • ServiceLoaderIt’s not thread-safe.