java 进阶 SPI机制

什么是SPI机制?

SPI的英文全称为Service Provider Interface,即为服务提供者接口。这个机制简单点理解就是:为某个接口寻找服务实现的机制。

SPI规范

定义服务的通用接口,针对通用的服务接口,提供具体的实现类。
1.在jar包(服务提供者)的META-INF/services/目录中,新建一个文件,文件名为SPI接口的"全限定名"。 文件内容为该接口的具体实现类的"全限定名"。
2.将spi所在jar放在主程序的classpath中。
3.服务调用方使用jdk提供的java.util.ServiceLoader去动态加载具体的实现类到JVM中。

SPI应用

新建一个maven工程,在工程的src/main/resources/META-INF目录下创建services文件夹,如下:

image.png

1.定义接口。


image.png

2.对接口进行实现。


image.png

3.在src/main/resources/META-INF/services目录下创建以接口'全限定名'的文件,把接口的实现类的全类名放到里面,如下:


image.png

编译工程后的文件在jar包下的META-INF/services目录下:


image.png

4.如何使用
建一个工具类SpiUtils,代码如下:

package com.study.rpc.common.tools;
import java.util.ServiceLoader;

/**
 * SPI机制 动态扩展
 * SPI ,全称为 Service Provider Interface,是一种服务发现机制。
 * 它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。
 * 要在ClassPath路径下配置添加一个文件。文件名字是 接口的全限定类名,内容是实现类的全限定类名,多个实现类用换行符分隔。
*
* Protocol protocol = (Protocol) SpiUtils.getServiceImpl(protocolConfig.getName(), Protocol.class);
 */
public class SpiUtils {

    /**
     * @param serviceName 实现类的名称
     * @param classType   实现类的接口class
     * @return 返回需要的实现类的对象
     */
    public static Object getServiceImpl(String serviceName, Class classType) {
        // 创建具体实现 -- jdk 加载  名称  ,第三方扩展
        //resources下 META-INF services 路径下新建一个路径全称的文件,指定的文件接口的实现类
        //返回这个接口的所有实现类
        ServiceLoader services =
                ServiceLoader.load(classType, Thread.currentThread().getContextClassLoader());
        // 根据服务定义的协议,依次暴露,如果有多个协议那就暴露多次
        for (Object s : services) {
            System.out.println("服务定义的协议匹配:" + s.getClass().getSimpleName());
            if (serviceName.equals(s.getClass().getSimpleName())) {
                return s;
            }
        }
        return null;
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容