In-Depth Analysis of Spring Boot’s SPI Mechanism

👉 This may be useful to you‘s community

🐱 One-on-one communication/interview booklet/resume optimization/job-seeking advice, welcome to joinYudao Rapid Development Platform」knowledge planet. Below are some materials provided by the planet:

  • 《Project Practical (Video)》: Learn from the book, practice in reality
  • 《High-Frequency Interview Questions》: Learning facing the resume, spring blossoms
  • 《Architecture x System Design》: Crushing everything, mastering high-frequency interview scenario questions
  • 《Java Learning Guide》: Systematic learning, mainstream technology stack in the internet
  • 《Must-Read Java Source Code Column》: Knowing the why and how

In-Depth Analysis of Spring Boot's SPI Mechanism

👉This may be a useful open-source project

Domestic Star project breaking 10w+, front end includes management backend + WeChat mini program, back end supports monolithic and microservices architecture.

Features include RBAC permissions, SaaS multi-tenancy, data permissions, e-commerce, payment, workflow, large-screen reports, WeChat public accounts, and more:

  • Boot Repository: https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud Repository: https://gitee.com/zhijiantianya/yudao-cloud
  • Video Tutorial: https://doc.iocoder.cn

[First batch in the country] supports JDK 21 + SpringBoot 3.2.2, JDK 8 + Spring Boot 2.7.18 dual versions

Source: juejin.cn/post/7132742686099898398

  • Java SPI Implementation
  • Example Explanation
    • Create Dynamic Interface
    • Implementation Class 1
  • Implementation Class 2
  • Related Tests
  • Running Results:
  • Source Code Analysis
  • Spring SPI
  • Spring Example
    • Define Interface
    • Related Implementations
    • Related Test Classes
    • Output Results
  • Source Code Analysis

In-Depth Analysis of Spring Boot's SPI Mechanism

SPI(Service Provider Interface) is a built-in service discovery mechanism in JDK, which can be used to enable framework extensions and replace components, mainly used in framework development, such as Dubbo, Spring, Common-Logging, JDBC, etc. using SPI mechanism, providing different implementations for the same interface to different users, thus improving the framework’s extensibility.

Java SPI Implementation

The built-in SPI in Java parses files named by the fully qualified name of the interface in the META-INF/services/ directory of classPath and jar packages through the java.util.ServiceLoader class, and loads the specified interface implementation classes in that file to complete the call.

Based on Spring Boot + MyBatis Plus + Vue & Element to implement a backend management system + user mini program, supporting RBAC dynamic permissions, multi-tenancy, data permissions, workflow, third-party login, payment, SMS, e-commerce, and other functions

  • Project Address: https://github.com/YunaiV/ruoyi-vue-pro
  • Video Tutorial: https://doc.iocoder.cn/video/

Example Explanation

Create Dynamic Interface

public interface VedioSPI
{
    void call();
}

Implementation Class 1

public class Mp3Vedio implements VedioSPI
{
    @Override
    public void call()
    {
        System.out.println("this is mp3 call");
    }

}

Based on Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element to implement a backend management system + user mini program, supporting RBAC dynamic permissions, multi-tenancy, data permissions, workflow, third-party login, payment, SMS, e-commerce, and other functions

  • Project Address: https://github.com/YunaiV/yudao-cloud
  • Video Tutorial: https://doc.iocoder.cn/video/

Implementation Class 2

public class Mp4Vedio implements VedioSPI
{
    @Override
    public void call()
    {
       System.out.println("this is mp4 call");
    }

}

Create a META-INF/services/ directory under the project’s source directory, and create a com.skywares.fw.juc.spi.VedioSPI file.

In-Depth Analysis of Spring Boot's SPI Mechanism

Related Tests

public class VedioSPITest
{
    public static void main(String[] args)
    {
        ServiceLoader<VedioSPI> serviceLoader =ServiceLoader.load(VedioSPI.class);
        
        serviceLoader.forEach(t->{
            t.call();
        });
    }
}

Note: The Java implementation of SPI is to find the service provider through the ServiceLoader tool class.

Running Results:

In-Depth Analysis of Spring Boot's SPI Mechanism

Source Code Analysis

The above is just a simple example to implement the built-in SPI functionality of Java. The implementation principle is that ServiceLoader is a built-in Java tool class used to find service provider interfaces, by calling the load() method to find service provider interfaces, and finally traversing to access the implementation classes of service provider interfaces one by one.

In-Depth Analysis of Spring Boot's SPI Mechanism

From the source code, we can find:

  • The ServiceLoader class itself implements the Iterable interface and implements its iterator method. In the implementation of the iterator method, it calls the method of the LazyIterator internal class to create an instance of the iterator.
  • All service provider interface corresponding files are placed in the META-INF/services/ directory, and the final type determines that the PREFIX directory cannot be changed.

Although the SPI mechanism provided by Java has a very good idea, it also has corresponding drawbacks. Specifically as follows:

  • The built-in Java method can only be obtained through traversal
  • The service provider interface must be placed in the META-INF/services/ directory.

Regarding the problems of Java’s SPI, Spring’s SPI mechanism follows the idea of SPI but expands and optimizes it.

Spring SPI

Spring SPI follows the design idea of Java SPI, and Spring uses the spring.factories method to implement the SPI mechanism, which can provide extensibility of the Spring framework without modifying the Spring source code.

Spring Example

Define Interface

public interface DataBaseSPI
{
   void getConnection();
}

Related Implementations

##DB2 Implementation
public class DB2DataBase implements DataBaseSPI
{
    @Override
    public void getConnection()
    {
        System.out.println("this database is db2");
    }

}

##Mysql Implementation
public class MysqlDataBase implements DataBaseSPI
{
    @Override
    public void getConnection()
    {
       System.out.println("this is mysql database");
    }

}

1. In the project’s META-INF directory, add a new spring.factories file

In-Depth Analysis of Spring Boot's SPI Mechanism

2. Fill in the relevant interface information, as follows:

com.skywares.fw.juc.springspi.DataBaseSPI = com.skywares.fw.juc.springspi.DB2DataBase, com.skywares.fw.juc.springspi.MysqlDataBase

Note that multiple implementations are separated by commas.

Related Test Class

public class SpringSPITest
{
    public static void main(String[] args)
    {
         List<DataBaseSPI> dataBaseSPIs =SpringFactoriesLoader.loadFactories(DataBaseSPI.class, 
                 Thread.currentThread().getContextClassLoader());
         
         for(DataBaseSPI datBaseSPI:dataBaseSPIs){
            datBaseSPI.getConnection();
         }
    }
}

Output Results

In-Depth Analysis of Spring Boot's SPI Mechanism

From the example, we can see that Spring uses spring.factories to implement SPI is very similar to Java’s implementation of SPI, but Spring’s SPI method has made relevant optimizations to Java’s SPI, specifically as follows:

  • Java SPI is a service provider interface corresponding to a configuration file, and the configuration file stores all implementation classes of the current interface, multiple service provider interfaces correspond to multiple configuration files, and all configurations are under the services directory;
  • Spring factories SPI is a spring.factories configuration file that stores multiple interfaces and their corresponding implementation classes, using the fully qualified name of the interface as the key and the implementation class as the value to configure, multiple implementation classes are separated by commas, only one configuration file spring.factories.

So how does Spring achieve SPI by loading spring.factories? We can further analyze through the source code.

Source Code Analysis

In-Depth Analysis of Spring Boot's SPI Mechanism

Note: loadFactoryNames parses the fully qualified names of the implementation classes specified in the spring.factories file, the specific implementation is as follows:

In-Depth Analysis of Spring Boot's SPI Mechanism

Note: Get all jar package META-INF/spring.factories file paths and return as an enumeration. Traverse the spring.factories file paths, load and parse them one by one, integrate the names of implementation classes of factoryClass types, and after obtaining the fully qualified names of implementation classes, instantiate them. The relevant source code is as follows:

In-Depth Analysis of Spring Boot's SPI Mechanism

Note: Instantiation is achieved through reflection to initialize the corresponding classes.

Welcome to join my knowledge planet, to comprehensively improve technical capabilities.

👉 Joining method,long press” or “scan” the QR code below:

In-Depth Analysis of Spring Boot's SPI Mechanism

The content of the planet includes: project practice, interview recruitment, source code analysis, learning routes.

In-Depth Analysis of Spring Boot's SPI MechanismIn-Depth Analysis of Spring Boot's SPI MechanismIn-Depth Analysis of Spring Boot's SPI MechanismIn-Depth Analysis of Spring Boot's SPI MechanismIn-Depth Analysis of Spring Boot's SPI Mechanism

If the article is helpful, please like and share.
Thank you for your support (*^__^*)

Leave a Comment