0%

JDK SPI 服务发现机制

Java SPI 机制(Service Provider Interface)是动态加载 Service 服务的机制。我们能使用 ServiceLoader 实现 Java SPI 机制在我们应用中根据一系列规则加载服务。

Java SPI

Java SPI Components

  1. Service Provider Interface: An interface or abstract class that defines the contract for the service provider implementation classes.
  2. Service Providers: The implementation classes that actually provides the services.
  3. SPI Configuration File: A special file that provides the logic to look for the services implementations. The file name must be present in the META-INF/services directory. The file name should be exactly same as the service provider interface fully qualified name. Every line in the file have one implementation service class details, again the fully qualified name of the service provider class.
  4. ServiceLoader: The Java SPI main class that is used to load the services for a service provider interface. There are various utility methods in the ServiceLoader to get specific implementations, iterate through them, or reload the services again.

Java SPI Example

Let’s create an implementation of SPI and load some services using the ServiceLoader class.


1. Service Provider Interface

Let’s say we have a MessageServiceProvider interface that defines the contract for the service provider implementations.

package com.elijah.serviceproviders;

public interface MessageServiceProvider {

	void sendMessage(String message);
}

2. Service Provider Implementation Classes

We want to support email messages and push notification messages. So we will create two service provider implementations of MessageServiceProvider interface – EmailServiceProvider and PushNotificationServiceProvider.

package com.elijah.serviceproviders;

public class EmailServiceProvider implements MessageServiceProvider {

	public void sendMessage(String message) {
		System.out.println("Sending Email with Message = " + message);
	}

}
package com.elijah.serviceproviders;

public class PushNotificationServiceProvider implements MessageServiceProvider {

	public void sendMessage(String message) {
		System.out.println("Sending Push Notification with Message = " + message);
	}

}

3. Service Provider Configuration File

The configuration file has to be created in the META-INF/services directory. Its name should be “com.elijah.provider.MessageServiceProvider“. We will specify both the implementation classes in this file.

com.elijah.provider.impl.EmailServiceProvider
com.elijah.provider.impl.PushNotificationServiceProvider

4. ServiceLoader Example to Load Services

Finally, we have to load the services using the ServiceLoader class. Here is a simple test program showing its usage.

package com.elijah.provider;

import java.util.ServiceLoader;

public class ServiceLoaderTest {
  public static void main(String[] args) {
    ServiceLoader<MessageServiceProvider> serviceLoader = ServiceLoader.load(MessageServiceProvider.class);

    for (MessageServiceProvider service : serviceLoader) {
      service.sendMessage("Hello");
    }
  }
}

When we run the above program, we get the following output.

Sending Email with Message = Hello
Sending Push Notification with Message = Hello

The below image shows our final project structure and SPI components.

References

ServiceLoader API Doc