Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use spi in java

2025-03-30 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces how to use spi in java, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.

Preface

In the process of development, SDK provided by third parties is often used to complete some business expansion functions, such as calling third-party SMS, image verification code, face recognition and other functions, but the problem is that third-party SDK only provides standard functions. In some scenarios, developers also want to do some personalized customization and expansion based on these SDK. What should I do?

As a result, some excellent SDK expands some interfaces through the mechanism of SPI, and developers can do their own business expansion based on these SPI interfaces.

Summarize the idea of SPI: there are often different implementation schemes in each module of the system, such as the scheme of log module, the scheme of xml parsing, and so on. In order not to specify the implementation class when loading the module, we need a service discovery mechanism, and java spi provides such a mechanism. Somewhat similar to the idea of IoC, moving control of service assembly outside the program is especially important in modular design.

Java's SPI mechanism is widely used in many frameworks and middleware, such as springboot,Dubbo. It belongs to advanced Java development knowledge, so it is necessary to master it.

Here is a diagram to illustrate the principle of the SPI mechanism.

I. specifications for the use of SPI in JDK

Define a general service interface and provide specific implementation classes for the service interface

In the META-INF/services/ directory of the jar package, create a new file named "fully qualified name" of the interface, and the file content is the "fully qualified name" of the concrete implementation class of the interface.

Put the jar where spi is located in the classpath of the main program

The service caller uses java.util.ServiceLoader and the service interface as parameters to dynamically load the specific implementation class into the JVM

Case presentation

Case business background:

Provide a unified payment interface

There are two payment methods, Alipay and WeChat Pay, which actually provide SDK for different payment manufacturers.

The client is the customer project, that is, the user who calls the payment SDK

From the point of view of the structure of the project, it also follows the service specification of SPI, that is, under the resources directory, create a folder with a specified name and put the fully qualified name of the interface implementation into it, then the client only needs to rely on a specific SDK, and then it can be loaded into the dependent SDK service through serviceLoader

Client-side customer project import dependency

Service-common com.congge 1.0-SNAPSHOT ali-pay com.congge 1.0-SNAPSHOT wechat-pay com.congge 1.0-SNAPSHOT public class MainTest {public static void main (String [] args) {ServiceLoader loader = ServiceLoader.load (PayService.class) Loader.forEach (payService-> {System.out.println (payService); payService.pay (); System.out.println ("=";});}}

Run the test program for this client

Let's take a look at a key piece of code in serviceLoader, that is, when loading a service interface, we can find that this method finally needs to find the service implementation in the "META-INF/services" directory under the jar package where the implementation class of the interface is located. If it is found, it can be loaded and used.

Advantages of SPI

The advantage of using Java SPI mechanism is to decouple and separate the logic of the assembly control of the third-party service module from the business code of the caller.

Applications can enable framework extensions or replace framework components according to the actual business situation.

Shortcomings of SPI

SrviceLoader can only be obtained by traversing all, that is, all the implementation classes of the interface are loaded and instantiated once.

If you don't want to use some implementation class, it's also loaded and instantiated, which is a waste.

The way to get an implementation class is not flexible enough, it can only be obtained in the form of Iterator, and the corresponding implementation class cannot be obtained according to a parameter.

It is not safe for multiple instances of ServiceLoader class to be used by multiple concurrent multithreading, and lock control is required.

An Application of SPI Mechanism in actual production

In the actual project development of the editor, there is a requirement that the standard product provides a variety of implementations for single sign-on, such as based on cas scheme, ldap scheme, oauth3.0 scheme, etc., and provides a set of specific implementation for each scheme, that is, it is packaged into its own jar package.

When the standard product is shipped out of the factory and installed on the client, there will be a default implementation, that is, oauth3.0 implementation, but sometimes the client has its own set, such as cas server, then the customer wants to be able to interface with cas single sign-on, so, specific to the actual deployment of the project, it is necessary to do some specific parameter configuration on site, and the standard implementation can be switched to cas implementation, so the problem comes. How is the standard product done according to the parameter configuration?

In fact, it is also very simple, that is, the serviceLoader mechanism is used to automatically discover all single sign-on implementations that can be loaded into standard products. If no external configuration parameters are passed, the implementation of oauth3.0 will be used by default, otherwise, the implementation passed by external parameters will be used.

II. The use of SPI in DUbbo

It can be said that the dubbo framework is a good example of the use of spi. The dubbo framework itself is further encapsulated based on the SPI specification. From the above analysis of the advantages and disadvantages, my mother learned that the native SPI needs to traverse all the interface implementations when the client selects a service, which is a waste of resources, while dubbo has a better encapsulation and implementation on this basis. Let's learn about the SPI use of dubbo.

The SPI specification for Dubbo is:

API name: can be defined at will

Implementation class name: add an "identity dropout" string before the interface name to represent its own function

Provider profile path: in the directory to be looked up in turn is

META-INF/dubbo/internal

META-INF/dubbo

META-INF/services

Provider profile name: the fully qualified class name of the interface without an extension

Content of the provider configuration file: the content of the file is in the form of key=value. Value is the full class name of the implementation class of this interface. Key is optional, but it is generally the "identity dropout" of the implementation class (lowercase initials). One class name on one line

Provider loading: the ExtensionLoader class is equivalent to the ServiceLoader class in JDK SPI and is used to load all the implementation classes in the provider configuration file and create corresponding instances

An example of Dubbo's SPI

1. Create a maven project and import core dependencies

Org.apache.dubbo dubbo 3.0.0 junit junit 4.12

2. Define SPI interface

For example, there is an interface for issuing orders. Note that @ SPI should be added to the interface. The value in the note can be filled in or not. If it is filled in, please note that the name of the key value in the configuration file is the same as that in the configuration file. If so, the implementation corresponding to this key will be found by default when loading.

@ SPI ("alipay") public interface Order {String way ();}

3. Define the implementation classes of the two interfaces

Public class AlipayOrder implements Order {public String way () {System.out.println ("using Alipay"); return "Alipay";}} public class WechatOrder implements Order {public String way () {System.out.println ("WeChat Pay"); return "WeChat Pay";}}

4. Define the extension class profile

Alipay=com.congge.spi.AlipayOrderwechat=com.congge.spi.WechatOrder

5. Test method

@ Test public void test1 () {ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader (Order.class); Order alipay = extensionLoader.getExtension ("alipay"); System.out.println (alipay.way ()); Order wechat = extensionLoader.getExtension ("wechat"); System.out.println (wechat.way ());}

If you do not specify which one to load, and the interface is configured with a default value, you only need to set "true" in getExtension, and the default one will be loaded automatically.

In the Dubbo source code, there are three kinds of code in many places, namely, adaptive extension point, named extension point, and active extension point. Dubbo implements many plug-and-pull functions through these extended spi interfaces.

ExtensionLoader.getExtensionLoader (xxx.class) .getAdaptiveExtension (); ExtensionLoader.getExtensionLoader (xxx.class) .getExtension (name); ExtensionLoader.getExtensionLoader (xxx.class) .getActivateExtension (url, key)

Take Protocol in dubbo source code as an example, corresponding to rpc module in dubbo source code

SPI ("dubbo") public interface Protocol {int getDefaultPort (); @ Adaptive Exporter export (Invoker invoker) throws RpcException; @ Adaptive Invoker refer (Class type, URL url) throws RpcException; void destroy ();}

Protocol protocol = ExtensionLoader.getExtensionLoader (Protocol.class). GetAdaptiveExtension ()

Protocol interface. At run time, dubbo will determine which implementation class of this Protocol interface should be selected to instantiate the object.

If you configure Protocol, the Protocol implementation class you configured will be loaded into JVM, and then when the object is instantiated, just use the Protocol implementation class that you configured

The above line of code is widely used in dubbo, that is, for many components, it retains an interface and multiple implementations, and then dynamically finds the corresponding implementation class according to the configuration when the system is running. If you don't have a configuration, go to the default implementation class, dubbo.

III. The use of SPI thought in springboot

We know that compared with spring, the springboot framework simplifies a lot from the configuration file, but what is simplified is only what the developers see in the xml configuration file, and its essence remains the same. Even if the xml configuration file is missing, it still needs to do configuration parsing work when starting, such as parsing the contents of the xml configuration file of the original database connection and loading it into the spring container.

In the case of springboot, many invisible configuration files are automatically read, parsed and loaded during container startup, and in the process, we can't help but wonder where these configurations exist. Here we use the idea of SPI, that is, the automatic assembly process of springboot.

For example, how does springboot know that it needs to load the bean object of DataSource, a database connection, at startup? How do you know whether to use JdbcTemplate or Druid connections?

In the process of starting the spingboot project, there is a very important work, that is, to complete the automatic assembly process of bean. What is the automatic assembly? To put it simply:

Scan files with specific fully qualified names in all dependent jar wrappers under classpath (project directory), parse them and assemble them into bean

Scan xml files, parse xml configurations and assemble them into bean

Parse configuration classes that are considered to need to be assembled, such as @ configuration,@service, etc.

What are the files in the first step? They are actually those / META-INF files in dubbo or native spi specifications, except that in springboot projects, the naming format and specification are slightly different.

Let's look at the source code to see how these spi files are loaded during springboot startup.

Then come here and focus on the setInitializers method, which, as the name implies, indicates some initialization settings to be made during startup, so what should be set?

In this method, there is a method getSpringFactoriesInstances, which is followed by this method.

In this method, you need to focus on this code, through which the files that depend on the package to be assembled are loaded. To put it bluntly, it is to load the name in the files of spring.factory under classpath.

SpringFactoriesLoader.loadFactoryNames (type, classLoader)

So the question is, what kind of files are loaded? You might as well continue to click in and take a look. At the beginning of the SpringFactoriesLoader class, there is such a path. You must have guessed what it is.

In other words, we will look for files that end with this name, for example, in the dependent jar package, we will see the following scene, in this spring.factories, we will see more familiar configurations.

In this way, the problem is very clear, by finding the spring.factories file, and then parsing the complete name of the concrete class, and then completing the initialization and loading of these extended SPI interfaces in the method: createSpringFactoriesInstances, that is, completing the process of configuration.

Thank you for reading this article carefully. I hope the article "how to use spi in java" shared by the editor will be helpful to everyone. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report