1.1 SPI(Service Provider Interface)

0 27
1 Introduction to SPI1.1 SPI(Service Provider Interface)Essentially: Configure t...

1 Introduction to SPI

1.1 SPI(Service Provider Interface)

Essentially: Configure the fully qualified name of the interface implementation class in the file, and have the service loader read the configuration file to load the implementation class. This can dynamically replace the implementation class of the interface at runtime.

java SPI: It is designed for service providers to use as plugins. It implements a dynamic loading mechanism based on the strategy pattern. We define only one interface in the program, and the specific implementation is entrusted to different service providers; at program startup, read the configuration file, and the implementation to be called is determined by the configuration.

dubbo SPI: There is also an SPI mechanism in dubbo. Although both need to configure the fully qualified name of the interface in the file, dubbo does not use the java spi mechanism but implements a stronger SPI mechanism independently, which supports AOP and dependency injection, and improves the performance of loading implementation classes by using caching. It also supports flexible acquisition of implementation classes. Based on SPI, it is easy to extend Dubbo. For example, the protocol and LoadBalance in dubbo are all extended through the SPI mechanism.

2. Java SPI

2.1 Implementation Process

1) A directory needs to be created under classpath, and the name of the directory must be: META-INF/service
2) Create a text file in the directory, which needs to meet the following conditions

  • The filename must be the full path name of the extended interface
  • The file internally describes all the implementation classes of the extended interface
  • The file encoding format is UTF-8

3) Load services through the loading mechanism of java.util.ServiceLoader

2.2 Working Principle

1) When calling the ServiceLoader.load(Class clz) method, it will read the file from the directory 'META-INF/services/' + clz.getName in the jar.

2) When calling the ServiceLoader.forEach() method, the actual process is carried out by LazyIterator. When calling LazyIterator.hasNext(), the actual service implementation classes are read from the file and are obtained by calling Class.forName(String name, boolean initialize, ClassLoader loader).

2.3 Actual Application

The most familiar application of javaSPI to us is the database driver, where mysql and oracle drivers have their own implementations for JDBC, which relies on the java SPI mechanism.

3 dubbo SPI

3.1 Implementation Process

1) It is necessary to create a directory under classpath, the name of which can be: META-INF/service/, META-INF/dubbo/, or META-INF/dubbo/internal/

2) Create a text file in the directory, which needs to meet the following conditions

  • The filename must be the full path name of the extended interface
  • The file internally describes all the implementation classes of the extension interface, writing the service implementation class in the form of KV key-value pairs, where Key is the name of the extension class, and Value is the fully qualified name of the implementation class.

3) Load the service through the loading mechanism of org.apache.dubbo.common.extension.ExtensionLoader

3.2 Working Principle

1) We first obtain an ExtensionLoader instance of an interface through the getExtensionLoader method of ExtensionLoader, and then obtain the extension class object through the getExtension method of ExtensionLoader, the source code is as follows, the first is getExtensionLoader method:

The source code of new ExtensionLoader(type) is as follows:

Note that the constructor of the ExtensionLoader object is as follows: ExtensionLoader.getExtensionLoader gets the extension class of the ExtensionFactory interface, and then gets the target extension class from the extension class through getAdaptiveExtension.

2) After obtaining the interface loader Loader through ExtensionLoader.getExtensionLoader, the extension class object needed is then obtained through the getExtension method.

The above code first checks the instance cache in holder, and if the cache is not hit, it creates an extension object. Dubbo contains a large number of extension point caches. This is a typical approach of using space for time.

The steps to create an extension class object are as follows:

  1. All extension classes are loaded from the configuration file through getExtensionClasses, and then the target extension class is obtained through the name.
  2. Create extension objects through reflection
  3. Inject dependencies into the extension object
  4. Wrap the extension object in the corresponding Wrapper object

We will focus on the getExtensionClasses method next:

First, retrieve the class from the cache. If the cache does not hit, call the loadExtensionClasses method to load. Let's take a look at the loadExtensionClasses method:

We see that multiple strategies are called to load classes here. It is very interesting to find that dubbo uses the javaSPI method to load class key-value pairs from the META-INF directory

Here, dubbo loads 3 types of class loading strategies using javaSPI:

org.apache.dubbo.common.extension.DubboInternalLoadingStrategy is used to load classes from META-INF/dubbo/internal/
org.apache.dubbo.common.extension.DubboLoadingStrategy is used to load classes from META-INF/dubbo/
org.apache.dubbo.common.extension.ServicesLoadingStrategy is used to load classes from META-INF/service/
Dubbo's SPI also provides adaptive (Adaptive) and automatic injection functions, which will not be expanded here. Those who are interested can learn more on their own.

3.3 Practical Application

Dubbo extensively uses the SPI mechanism:

For example, the implementation of multiple protocols in dubbo:

4 Comparison between javaSPI and dubboSPI

  1. When Java SPI loads extension points, it loads all available extension points at once, many of which are not needed, which will waste system resources. dubboSPI selectively loads the required SPI interfaces.
  2. In the javaSPI configuration file, all the extension implementations are simply listed without naming them, which makes it difficult to accurately refer to them in the program. In contrast, the dubboSPI configuration file uses aliases in the form of key-value pairs, which is easy to distinguish.
  3. If the SPI extension depends on other extensions, javaspi cannot achieve automatic injection and assembly, but dubbo can realize it.
  4. javaSPI does not provide functions similar to Spring's IOC and AOP, while dubboSPI supports them

Author: Gong Hanglin, JD Logistics

Source: JD Cloud Developer Community, TechTalk by猿其说Tech. Please indicate the source when reproduced

你可能想看:
最后修改时间:
admin
上一篇 2025年03月25日 10:28
下一篇 2025年03月25日 10:51

评论已关闭