Author:sigangjun
blog.csdn.net/sigangjun/article/details/79071850
The full name of SPI is: Service Provider Interface. Most developers may not be familiar with it because it is aimed at vendors or plugins. There is a detailed introduction in the documentation of java.util.ServiceLoader.
To summarize the idea of the Java SPI mechanism briefly: in our system, the various abstract modules often have many different implementation solutions, such as logging modules, XML parsing modules, JDBC module solutions, etc. In object-oriented design, we generally recommend that modules be programmed based on interfaces, avoiding hardcoding of implementation classes between modules.
Once the code involves specific implementation classes, it violates the plug-in principle. If you need to replace an implementation, you will need to modify the code. To achieve dynamic specification of implementations during module assembly, a service discovery mechanism is required.
The Java SPI provides such a mechanism: it is a mechanism for finding service implementations for a certain interface. It is somewhat similar to the idea of IOC, which shifts the control of assembly outside the program. This mechanism is especially important in modular design.
The specific convention of Java SPI is: when a service provider provides an implementation of a service interface, a file named after the service interface must be created in the META-INF/services/ directory of the JAR package. This file contains the specific implementation class that implements the service interface.
When an external program assembles this module, it can find the specific implementation class name through the configuration file in META-INF/services/ of the JAR package, instantiate it, and complete the injection of the module.
Based on this convention, we can easily find the implementation class of the service interface without specifying it in the code. The JDK provides a utility class for service implementation lookup: java.util.ServiceLoader.
1. common-logging
This is the facade interface for logging provided by Apache. There is only an interface, no implementation. The specific solution is implemented by each provider. The log provider is discovered by scanning the META-INF/services/org.apache.commons.logging.LogFactory configuration file, reading the contents of this file to find the log provider’s implementation class.
As long as our logging implementation contains this file and specifies the implementation class of the LogFactory factory interface in the file, we can get more Java technical content by replying with the keyword: Java on the WeChat official account of Java Technology Stack.
2. jdbc
Before JDBC 4.0, developers needed to load drivers based on Class.forName(“xxx”). JDBC 4 also uses the SPI mechanism to discover driver providers, allowing the implementation class to be specified in the META-INF/services/java.sql.Driver file.
A content management system has a search module. It is based on interface programming. The implementation of the search may be based on file system search or database search.
The interface is defined as follows:
package my.xyz.spi;
import java.util.List;
public interface Search {
public List serch(String keyword);
}
Company A implements the Search interface using file system search, while Company B implements it using database search.
-
Class implemented by Company A: com.A.spi.impl.FileSearch
-
Class implemented by Company B: com.B.spi.impl.DatabaseSearch
When Company A releases the implementation JAR package, it must write the following content in the META-INF/services/my.xyz.spi.Search file:
com.A.spi.impl.FileSearch
When Company B releases the implementation JAR package, it must write the following content in the META-INF/services/my.xyz.spi.Search file:
com.B.spi.impl.DatabaseSearch
Below is the SPI test code:
package com.xyz.factory;
import java.util.Iterator;
import java.util.ServiceLoader;
import my.xyz.spi.Search;
public class SearchFactory {
private SearchFactory() {
}
public static Search newSearch() {
Search search = null;
ServiceLoader<Search> serviceLoader = ServiceLoader.load(Search.class);
Iterator<Search> searchs = serviceLoader.iterator();
if (searchs.hasNext()) {
search = searchs.next();
}
return search;
}
}
Reply with the keyword: Java on the WeChat official account of Java Technology Stack to get more Java technical content.
Recent Content Sharing
How to Choose Between Spring Cloud Gateway and Zuul?
46 PPTs to Understand JVM, GC Algorithms, and Performance Tuning!
How to Split Databases and Tables, Vertically? Horizontally?
How Does Zookeeper Implement Distributed Locks?
Sharing a Learning Resource for Java Architects
Feeling lost in learning and work?
Click “Read Original” to join the small circle of Java enthusiasts!