Article directory
1. SPI Interpretation: What is SPI?
SPI
( Service Provider Interface
) is a service discovery mechanism that allows third-party providers to provide implementations or extensions to the core library or main framework. This design allows core libraries/frameworks to enhance functionality through third-party implementations without modifying their own code.
- JDK native SPI :
-
Definition and discovery :
JDK
ItSPI
mainlyMETA-INF/services/
specifies which classes implement a given service interface by placing specific files in the directory. The name of these files should be the fully qualified name of the interface and the contents should be the fully qualified class name that implements the interface. -
Loading mechanism : The class loader mechanism
ServiceLoader
used by the class loads and instantiates service providers from the directory. For example, an implemented instance iterator is returned .Java
META-INF/services/
ServiceLoader.load(MyServiceInterface.class)
MyServiceInterface
-
Disadvantages :
JDK
The native one will initialize a new instanceSPI
every time it is loaded, does not implement class caching, and does not consider advanced features such as singletons.ServiceLoader
- Spring's SPI :
-
More flexible :
Spring
ItSPI
is not just service discovery, it provides a complete plug-in mechanism. For example, you canSpring
define new onesPropertySource
,ApplicationContextInitializer
etc. -
Integrated with IoC : Unlike
JDK
IoCSPI
, IoC is integrated with itsSpring
( IoC ) container, allowing full functionality such as dependency injection to be leveraged in the implementation .SPI
IoC
Inversion of Control
SPI
Spring
-
Condition matching : Provides a condition-based matching mechanism, which allows only specific implementations
Spring
to be loaded under certain conditions . For example, you can choose which database driver to load based on the current running environment.SPI
-
Configuration :
Spring
Allows configurationspring.factories
in a directory through files , this is very similar to , but it provides more functionality and flexibility.META-INF
JDK
SPI
Give an analogy example:
Imagine we are building a television, SPI
like a socket on the television USB
. This socket can be plugged into various devices (such as USB flash drives, game controllers, TV sticks, etc.), but we don't care about the inner workings of these devices. In this way, only a standard interface needs to be provided, and other companies (such as USB disk manufacturers) can provide implementations for this interface. This way, the TV can use a variety of new devices without changing its own internal code, and device manufacturers can make compatible devices for various TV sets.
In short, SPI
it is a design pattern that separates interface definition and implementation. It encourages third parties to provide plug-ins or implementations for a core product or framework, so that the core product can easily extend its functionality.
2. Application examples of SPI in JDK
In Java
the ecosystem, SPI
it is a core concept that allows developers to provide extensions and alternative implementations without having to change the core library or application. An example is given below to illustrate.
All codes and steps are as follows:
Step 1 : Define a service interface, file name:MessageService.java
package com.example.demo.service;
public interface MessageService {
String getMessage();
}
Step 2 : Provide implementation for the service interface. Two simple implementation classes will be provided here.
HelloMessageService.java
package com.example.demo.service;
public class HelloMessageService implements MessageService {
@Override
public String getMessage() {
return "Hello from HelloMessageService!";
}
}
HiMessageService.java
package com.example.demo.service;
public class HiMessageService implements MessageService {
@Override
public String getMessage() {
return "Hi from HiMessageService!";
}
}
These implementations are like different makes or models of USB flash drives or other USB
devices. Each device has its own functions and features, but all adhere to the same USB
standards.
Step 3 : Register a service provider
src/main/resources/
Create a META-INF/services/
folder named under the resources directory (usually ). In this folder, create a com.example.demo.service.MessageService
file called (this is the fully qualified name of our interface ). This file does not have any file extension, so do not add .txt
such a suffix. The contents of the file should be the fully qualified names of our two implementation classes, one on each line:
com.example.demo.service.HelloMessageService
com.example.demo.service.HiMessageService
META-INF/services/
Is a specific directory that is agreed upon in the Java SPI
( ) mechanism. Service Provider Interface
It is not chosen arbitrarily but SPI
is clearly defined in the specification. Therefore, when using JDK
the ServiceLoader
class to load a service provider, it will specifically look for files in this path.
Please make sure that the file has only one name per line and that there are no extra spaces or hidden characters and that the file uses UTF-8
the encoding.
Step 4 : ServiceLoader
Load and consume services using
package com.example.demo;
import com.example.demo.service.MessageService;
import java.util.ServiceLoader;
public class DemoApplication {
public static void main(String[] args) {
ServiceLoader<MessageService> loaders = ServiceLoader.load(MessageService.class);
for (MessageService service : loaders) {
System.out.println(service.getMessage());
}
}
}
The running results are as follows:
This shows that the two implementations we provided ServiceLoader
for the interface were successfully loaded , and that we can extend our service by adding more implementation classes and updating files without modifying the class's code .MessageService
Main
META-INF/services/com.example.MessageService
Imagine buying a high-end smart TV. This TV has one or more HDMI
ports on it. This is how it connects to external devices.
-
Define the service interface : This is like a standard that defines
HDMI
a port for a TV. In the code above,MessageService
the interface is the "HDMI
port" that defines how to communicate with external devices. -
Providing implementations for service interfaces : This is similar to manufacturers
HDMI
producing interfaces for various devices, such as game consoles, Blu-ray players or streaming sticks. In code,HelloMessageService
andHiMessageService
are these "HDMI
devices". Each device/implementation has its own unique output, but all follow a unifiedHDMI
standard (MessageService
interface). -
Registered Service Provider : When we purchase a
HDMI
device, it is usually clearly marked "Suitable for" on the boxHDMI
. This is like a logo telling the user that it can be connected to anyHDMI
TV with an interface. InSPI
the example,META-INF/services/
the directory and the files within it act like this "label" that tellsJDK
which classes areMessageService
implemented. -
Use ServiceLoader to load and use services : When a
HDMI
device is plugged into the TV and switched to the correct input channel, the TV will display the device's content. Similarly, in this step of the code,ServiceLoader
like the TV's input selection function, is able to discover and use all connectedHDMI
devices (i.e.MessageService
all implementations of ).
3. Application of SPI in Spring framework
Spring
The official mentioned the concept of SPI
( Service Provider Interface
) many times in its documentation and source code. However, when we say " Spring
of SPI
", we usually refer to Spring
the set of extensible interfaces and abstract classes provided by the framework to developers, and developers can implement their own versions based on these interfaces and abstract classes.
In Spring
, SPI
the concept and the file mechanism Spring Boot
used spring.factories
are not exactly the same, but they all embody the ideas of pluggability and extensibility.
- Spring's SPI :
Spring
The core framework provides many interfaces and abstract classes, such asBeanPostProcessor
,PropertySource
,ApplicationContextInitializer
etc., which can be regardedSpring
asSPI
. Developers can implement these interfaces to extendSpring
the functionality. These interfaces allow developersSpring
to intervene at different stages of the container's life cycle to implement their own logic.
- Spring Boot’s spring.factories mechanism :
-
spring.factories
IsSpring Boot
a feature that allows developers to customize automatic configuration. Throughspring.factories
files, developers can define their own auto-configuration classes, whichSpring Boot
will be automatically loaded at startup. -
In this case,
SpringFactoriesLoader
the use, specifically viaspring.factories
a file to load and instantiate a defined class, can be seen as anSPI
implementation-specific approach, but it is specific toSpring Boot
.
3.1 SPI ideas in the traditional Spring framework
In the traditional Spring
framework, although "SPI"
the term named is not used directly, the core idea still exists. Spring
Provides multiple extension points, the most representative of which is BeanPostProcessor
. MessageService
In this section, we will explore how to take advantage of the ideas embodied by extension points through a simple interface Spring
and BeanPostProcessor
its implementation SPI
.
Two simple implementation classes are provided.
HelloMessageService.java
package com.example.demo.service;
public class HelloMessageService implements MessageService {
@Override
public String getMessage() {
return "Hello from HelloMessageService!";
}
}
HiMessageService.java
package com.example.demo.service;
public class HiMessageService implements MessageService {
@Override
public String getMessage() {
return "Hi from HiMessageService!";
}
}
definitionBeanPostProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class MessageServicePostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof MessageService) {
return new MessageService() {
@Override
public String getMessage() {
return ((MessageService) bean).getMessage() + " [Processed by Spring SPI]";
}
};
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
Modify Spring
configuration
Will MessageServicePostProcessor
be added to Spring
the configuration:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MessageServiceConfig {
@Bean
public MessageService helloMessageService() {
return new HelloMessageService();
}
@Bean
public MessageService hiMessageService() {
return new HiMessageService();
}
@Bean
public MessageServicePostProcessor messageServicePostProcessor() {
return new MessageServicePostProcessor();
}
}
execute program
Using the example class provided earlier DemoApplication
:
package com.example.demo;
import com.example.demo.configuration.MessageServiceConfig;
import com.example.demo.service.MessageService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class DemoApplication {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(MessageServiceConfig.class);
MessageService helloMessageService = context.getBean("helloMessageService", MessageService.class);
MessageService hiMessageService = context.getBean("hiMessageService", MessageService.class);
System.out.println(helloMessageService.getMessage());
System.out.println(hiMessageService.getMessage());
}
}
operation result:
Now, each MessageService
implementation is BeanPostProcessor
processed, adding additional messages “[Processed by Spring SPI]”
. This demonstrates the Spring
concept SPI
of BeanPostProcessor
extending or modifying Spring
a container bean
.
Someone may have noticed the red warning here. As mentioned before BeanPostProcessor
, this situation will occur when BeanPostProcessor
one or more of them are processed. BeanPostProcessor
Simply put, some cannot handle early initialization because BeanPostProcessor
they need to be initialized before others , including configuration classes and others . The solution is not to initialize it in the configuration class, delete it in the configuration class, and then add annotations.bean
BeanPostProcessor
bean
BeanPostProcessor
MessageServicePostProcessor
MessageServicePostProcessor
@Component
Analogy to the TV example at the beginning of the article:
-
TV and USB Port : In this new example, TV is still the core
Spring
application, specificallyDemoApplication
the class. This core application needs toMessageService
get and print a message from some service (ie. -
USB socket : As before,
MessageService
the interface is this "USB
socket". It provides a standardized interface, that is,getMessage()
a method, for TVs, but does not specify how to implement it. -
Equipment Manufacturers and Their Products : Here we have two types of equipment manufacturers or third party providers:
HelloMessageService
andHiMessageService
. They provide different devices or implementations for "USB
sockets" (i.e. interfaces).MessageService
One shows“Hello from HelloMessageService!”
, the other shows“Hi from HiMessageService!”
. -
BeanPostProcessor : This is a special "magic box" that can be thought of as a smart device that can intercept and modify the content displayed on the TV. When you plug in
USB
a device (i.e.MessageService
an implementation of ) and try to get messages from it, this "magic box" steps in and adds for each message“[Processed by Spring SPI]”
. -
Spring context configuration : This is still the instruction manual of the TV, but now it uses
Java
a configuration method based on classes, that is,MessageServiceConfig
classes. This "instruction manual" instructsSpring
the container on how to create and manageMessageService
instances, and also instructs it on how to use "magic boxes" (i.e.MessageServicePostProcessor
) to process messages.
Overall, this new example provides a more dynamic scenario than the previous example, where the Spring
extension BeanPostProcessor
points allow us to intercept and modify bean
the behavior, like a smart device that can intervene and change the content displayed on the TV.
3.2 SPI idea in Spring Boot
Spring Boot
There is a SPI
similar mechanism to Java
the standard , but it's not exactly equivalent SPI
.
Spring Boot
The automatic configuration mechanism mainly relies on spring.factories
files. This file can jar
exist in multiple locations, and Spring Boot
all visible spring.factories
files will be loaded. We can declare a series of automatic configuration classes in this file, so that when certain conditions are met, these configuration classes will be automatically applied Spring Boot
.
A good example of the idea is shown next Spring SPI
, but it is Spring Boot
closely related.
Define interface
package com.example.demo.service;
public interface MessageService {
String getMessage();
}
Two simple implementation classes will be provided here.
HelloMessageService.java
package com.example.demo.service;
public class HelloMessageService implements MessageService {
@Override
public String getMessage() {
return "Hello from HelloMessageService!";
}
}
HiMessageService.java
package com.example.demo.service;
public class HiMessageService implements MessageService {
@Override
public String getMessage() {
return "Hi from HiMessageService!";
}
}
Registration service
resources/META-INF
Create a file named under spring.factories
. In this file, MessageService
implementation classes can be registered.
com.example.demo.service.MessageService=com.example.demo.service.HelloMessageService,com.example.demo.service.HiMessageService
Note that this com.example.demo.service.MessageService
is the full path of the interface, com.example.demo.service.HelloMessageService,com.example.demo.service.HiMessageService
but the full path of the implementation class. If there are multiple implementation classes, they should be separated by commas.
spring.factories
There must be no line breaks between entry keys and values in the file, i.e. key=value
the structure of the form must start on the same line. However, if there are multiple values that need to be listed (such as multiple implementation classes), and the values are comma separated, you can use backslash ( ) \
to break the line. spring.factories
The name is conventional. If you try to use a different file name, then Spring Boot
the autoconfiguration mechanism will not recognize it.
Here spring.factories
it can be written as
com.example.demo.service.MessageService=com.example.demo.service.HelloMessageService,\
com.example.demo.service.HiMessageService
Entering directly after the comma IDEA
will automatically complete the backslash, ensuring that there is no line break between the key and the value.
Use SpringFactoriesLoader
to load services
package com.example.demo;
import com.example.demo.service.MessageService;
import org.springframework.core.io.support.SpringFactoriesLoader;
import java.util.List;
public class DemoApplication {
public static void main(String[] args) {
List<MessageService> services = SpringFactoriesLoader.loadFactories(MessageService.class, null);
for (MessageService service : services) {
System.out.println(service.getMessage());
}
}
}
SpringFactoriesLoader.loadFactories
The second parameter is the class loader, here we use the default class loader, so pass it null
.
operation result:
This approach takes advantage of the API Spring
, SpringFactoriesLoader
which allows developers to provide multiple implementations of an interface and spring.factories
register them through files. This is very similar to the idea JDK
of SPI
but differs in the implementation details. This is also Spring Boot
the basis for automatic configuration. It will look for various spring.factories
files and initialize and configure them based on the classes defined in them bean
.
Let’s continue using the TV example to explain:
-
TV : This is our
Spring
app, likeDemoApplication
. A TV is a device that views different sources or channels, and our application is designed to run and use different service implementations. -
USB socket : This represents our
MessageService
interface.USB
A socket is a standard interface that allows the connection of various devices, just asMessageService
an interface allows multiple implementations. -
USB device (such as USB flash drive or mobile hard disk) : This represents our service implementation, such as
HelloMessageService
andHiMessageService
. EachUSB
device has specific content or functionality when plugged into the TV, just like each of our service implementations returns a different message. -
TV's USB device directory : This is
spring.factories
the file. When weUSB
plug a device into the TV, the TV checks the device's information or content, andspring.factories
the file tellsSpring Boot
which service implementations are available, just like the TV knows whichUSB
devices are plugged in. -
TV’s USB scanning function : That’s it
SpringFactoriesLoader
. When we want to viewUSB
content from the TV, the TV scans and displays the content. Likewise, whenDemoApplication
run, the service implementations listed in the fileSpringFactoriesLoader
are found and loaded .spring.factories
Simplified explanation:
-
When
USB
a device is plugged into a TV, the TV is expected to recognize and display the device's content. -
In our case,
USB
the content of the device isMessageService
the message returned from the implementation class. -
spring.factories
The file is like the TV's built-in directory, telling the TV whichUSB
devices are known and available for use. -
When our
DemoApplication
(television) is running, it usesSpringFactoriesLoader
(USB
scan function) to check which services (USB
devices) are available and outputs the appropriate message (displayUSB
content).
Summary: In this Spring Boot
example SPI
, we show Spring
how the core application automatically recognizes and uses the registered implementation in the file, similar to spring.factories
how a television automatically recognizes and uses all plugged-in devices.USB
4. Application of SPI in JDBC driver loading
The database driver SPI
is mainly reflected in JDBC
the automatic discovery mechanism of the driver. JDBC 4.0
Introduced a feature that allows drivers to automatically register to DriverManager
. This is achieved by Java
using . There will be a file in SPI
the driver package , which contains the full class name of the driver's implementation class. In this way, when there is a driver file in the classpath , the application can automatically discover and load the driver without explicitly loading the driver class.jar
META-INF/services/java.sql.Driver
Driver
JDBC
jar
Java
JDBC
This means that any database vendor can write its own JDBC
driver and as long as it adheres to JDBC
the driver's specifications SPI
, it can be used by any application that JDBC
uses it.Java
When we use to DriverManager.getConnection()
obtain a database connection, SPI
the mechanism behind it is used to load the appropriate driver.
Here's SPI
exactly how the mechanism works:
- Define service interface :
Here, the interface is already Java
defined by the platform, ie java.sql.Driver
.
- Provide an implementation for the interface :
Major database vendors (such as Oracle
, MySQL
, , PostgreSQL
etc.) provide JDBC
drivers for their databases, and they all implement java.sql.Driver
the interface. For example, MySQL
the driver has a class similar to the following:
public class com.mysql.cj.jdbc.Driver implements java.sql.Driver {
// 实现接口方法...
}
Directly above the picture:
- Register service provider :
For MySQL
the driver, you can find a file named in the directory JAR
of its files . The content of the file is as follows:META-INF/services
java.sql.Driver
com.mysql.cj.jdbc.Driver
Directly above the picture:
When you see this, do you find that it is the same as the example 2
given in Section 1 JDK SPI
? Experience it.
- Use SPI to load and use services :
When we call DriverManager.getConnection(jdbcUrl, username, password)
, all registered implementations DriverManager
will be found using . It then tries each driver until it finds one that can handle the given one .ServiceLoader
java.sql.Driver
jdbcUrl
Here is a simple example showing how to get JDBC SPI
a database connection using:
import java.sql.Connection;
import java.sql.DriverManager;
public class JdbcExample {
public static void main(String[] args) {
String jdbcUrl = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "password";
try {
Connection connection = DriverManager.getConnection(jdbcUrl, username, password);
System.out.println("Connected to the database!");
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
In the above code, we do not explicitly specify which JDBC
driver to use, as DriverManager
the appropriate driver is automatically selected for us.
This modular and plug-in mechanism makes it easy to switch drivers for different databases by simply changing JDBC URL
and ensuring that the corresponding driver JAR
is on the classpath.
In Spring Boot
, developers typically do not interact directly with JDBC
the SPI
mechanism to obtain a database connection. Spring Boot
The automatic configuration mechanism hides many low-level details, making configuring and using the database easier.
Generally, database connection information is configured in application.properties
or .application.yml
For example:
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
In the above steps, the automatic configuration mechanism will initialize and configure the object Spring Boot
based on the provided dependencies and configuration information . This object manages the database connection. DataSource
In fact, when adding JDBC
a driver dependency, the mechanism (applied in the specification) Spring Boot
will be used JDK
to find and load the corresponding database driver. Although developers do not directly interact with it , they do use mechanisms behind the scenes to obtain database connections.SPI
JDBC
JDK
SPI
Spring Boot
JDK SPI
5. How to understand SPI ideas through Spring Boot automatic configuration
This mechanism is somewhat similar Java
to SPI
, in that it allows third-party libraries to provide some default configuration. But it is more powerful and flexible than Java
, SPI
because Spring Boot
it provides a large number of annotations (such as @ConditionalOnClass
, @ConditionalOnProperty
, @ConditionalOnMissingBean
etc.) to control whether the auto-configuration class should be loaded and applied.
Overall, Spring Boot
the spring.factories
mechanisms of Java
and SPI
are conceptually similar, but they differ in implementation details and purpose.
Let's create a simplified practical example, assuming we want to create automatic configurations for different messaging services such as SMS
and .Email
MessageService interface :
package com.example.demo.service;
public interface MessageService {
void send(String message);
}
SMS service implementation :
package com.example.demo.service.impl;
import com.example.demo.service.MessageService;
public class SmsService implements MessageService {
@Override
public void send(String message) {
System.out.println("Sending SMS: " + message);
}
}
Email service implementation :
package com.example.demo.service.impl;
import com.example.demo.service.MessageService;
public class EmailService implements MessageService {
@Override
public void send(String message) {
System.out.println("Sending Email: " + message);
}
}
Automatic configuration class :
package com.example.demo.configuration;
import com.example.demo.service.EmailService;
import com.example.demo.service.MessageService;
import com.example.demo.service.SmsService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MessageAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "message.type", havingValue = "sms")
public MessageService smsService() {
return new SmsService();
}
@Bean
@ConditionalOnProperty(name = "message.type", havingValue = "email")
public MessageService emailService() {
return new EmailService();
}
}
This class provides two conditionals beans
(components), namely SmsService
and EmailService
. beans
The creation of these depends on application.properties
specific property values in the file.
- @ConditionalOnProperty(name = “message.type”, havingValue = “sms”)
This condition is when the value of the property defined in application.properties
or is . At this point, the method will be called, creating a .application.yml
message.type
sms
true
smsService()
SmsService
bean
- @ConditionalOnProperty(name = “message.type”, havingValue = “email”)
This condition is when the value of the property defined in application.properties
or is . At this point, the method will be called, creating a .application.yml
message.type
email
true
emailService()
EmailService
bean
spring.factories file :
src/main/resources/META-INF
Create a file in the directory with spring.factories
the following content:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.configuration.MessageAutoConfiguration
application.properties file :
message.type=sms
MessageTester component :
package com.example.demo;
import com.example.demo.service.MessageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class MessageTester {
@Autowired
private MessageService messageService;
@PostConstruct
public void init() {
messageService.send("Hello World");
}
}
DemoApplication main program :
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
operation result:
In the above example, we created an MessageService
interface and two implementations ( SmsService
and EmailService
). We then created an autoconfiguration class that contained two bean
definitions that were conditionally created bean
based on the property values in . application.properties
In spring.factories
the file, we declare this autoconfiguration class so that Spring Boot
it can be automatically loaded on startup.
Here, continue to use the example of a television to sublimate our understanding.
TV analogy
- General concept :
-
Suppose TV (
TV
) is anJava
application. -
Various slots of the TV, such as
HDMI
,USB
, ,VGA
etc., can be regarded as interfaces in the applicationSPI
. -
Devices plugged into these slots (such as
DVD
players, game consoles,USB
drives, etc.) can be consideredSPI
implementations.
- Java SPI :
-
When we buy a TV, we don't know what kind of device will be connected to it. It may be
DVD
a player or a game console. -
However, as long as the devices adhere to the standard for the slot (i.e.,
HDMI
a standard), you can plug it into your TV and have it work. -
This is like
Java
aSPI
mechanism: in order to allow multiple vendors to provide implementations,Java
an interface is defined, and vendors provide specific implementations.
- Spring Boot automatic configuration :
-
Now, imagine a modern smart TV. When a device is plugged in, the TV not only recognizes it, but may also automatically adjust settings based on the type of device connected, such as selecting the correct input source, optimizing image quality, and more.
-
This is like
Spring Boot
autoconfiguration: whenSpring Boot
the app starts, it checks forclasspath
the libraries on it and automatically configures the app based on the libraries that are present. -
The automatic settings of the TV can be compared to
Spring Boot
thespring.factories
and various@Conditional
... Notes. They determine which configuration is performed under what conditions.
- Scalability :
-
If a TV manufacturer wants to develop a TV for a new type of slot or connection technology, it can easily add the new slot to its TV models.
-
Likewise,
Spring Boot
if you want to add new features or libraries to your application, just add the relevant dependencies andSpring Boot
these new features will be automatically recognized and configured.
Using this analogy, the TV's slot and auto-configuration features provide us with an intuitive way to understand how the Java
mechanisms SPI
and Spring Boot
auto-configuration work, and how they provide convenience to application developers.
6. SPI (Service Provider Interface) Summary
SPI
, that is, the service provider interface, is a specific design pattern. It allows a framework or core library to provide a predefined interface to third-party developers, allowing them to provide custom implementations or extensions to the framework.
Core goals :
-
Decoupling:
SPI
The mechanism keeps the core of the framework decoupled from its extensions, so that the core code does not depend on the specific implementation. -
Dynamic loading: The system is able to dynamically discover and load the required implementation through specific mechanisms (such as
Java
) .ServiceLoader
-
Flexibility: Framework users can choose, replace or add new implementations according to their needs without modifying the core code.
Pluggable: Services or implementations provided by third parties can be easily added to or removed from the system without changing the existing code structure.
Value :
-
Provides users of the framework or library with more customization options and flexibility.
-
Allowing the core parts of the framework to remain stable while being able to accommodate new features and extensions.
SPI and "opening and closing principle" :
The "open-closed principle" advocates that software entities should be open to extension but closed to modification. That is, adding new functions through extension without changing the existing code.
How does SPI embody the "open-close principle" :
-
Open for extension:
SPI
Provides a standardized way for third-party developers to provide new implementations or functionality for existing systems. -
Closed to modification: When new functionality or features are added, the code of the original framework or library does not need to be modified.
-
Independent development: The framework and its
SPI
implementation can evolve and develop independently without affecting each other.
In short, SPI
it is an effective way to make a software framework or library more modular, extensible and maintainable. By following the "open-close principle", SPI
the stability and flexibility of the system are ensured to meet changing business needs.
Welcome to the one-click triple connection~
If you have any questions, please leave a message, let's discuss and learn together
----------------------Talk is cheap, show me the code----- ------------------