当前位置:   article > 正文

SPI示例学习_spi代码

spi代码

Service Provider Interface

它是从Java 6开始引入的,是一种基于ClassLoader发现并加载服务的机制。

服务发现机制:通过在ClassPath路径下的META-INFO/services文件夹中查找文件,并自动加载文件里所定义的类。

SPI机制可以很好的解决不同框架之间的扩展问题。在java.util.ServiceLoader#load(Class clazz)完成了SPI的实现。

SPI机制能够使接口与具体的实现类解耦,可以根据实际的业务情况启用或替换具体组件。

一个标准的SPI,由3个组件构成,分别是:

  • Service:一个公开的接口或抽象类,定义了一个抽象的功能模块。
  • Service Provider:是Service接口的一个实现类。
  • ServiceLoader:是SPI机制中的核心组件,负责在运行时发现并加载Service Provider。

Java SPI的运行流程

在这里插入图片描述

Java SPI的三大规范要素:

  1. 规范的配置文件:
  • 文件路径:必须在JAR包中的META-INFO/services目录下
  • 文件名称:Service接口的全限定名
  • 文件内容:Service实现类(及Service Provider类)的全限定名。如果有过个实现类,那么每一个实现类在文件中单独占据一行
  1. Service Provider类必须具备无参的默认构造方法

Service接口的实现类,即Service Provider类,必须具备无参的默认构造方法。因为随后通过反射技术实例化它时,是不带参数的。

  1. 保证能加载到配置文件和Service Provider类
  • 方式一:将Service Provider的JAR包放到classpath中(最常用)
  • 方式二:将JAR包安装到JRE的扩展目录中
  • 方式三:自定义一个ClassLoader

示例:

有一家公司(company),它需要连接互联网,它定义一个连接网络的API(network-api),由联通(unicom-network)和电信(telecom-network)来提供网络服务。项目目录如下:

在这里插入图片描述

InternetService服务接口定义:

package com.lwy.it;

/**
 * 定义了SPI中的Service接口
 */
public interface InternetService {
    void connectInternet();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

telecom-network模块,只有一个实现类:

package com.telecom.network;

import com.lwy.it.InternetService;

/**
 * TelecomNetwork 作为 Service Provider类,实现了InternetService接口
 */
public class TelecomNetwork implements InternetService {
    @Override
    public void connectInternet() {
        System.out.println("通过电信网络联网");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

注意:classpath下META-INF/service路径下,定义一个com.lwy.it.InternetService文件

文件名是Service接口的全限定名;文件内容是Service Provider类的全限定名,多个Service Provider用多行表示。

com.telecom.network.TelecomNetwork
  • 1

unicom-network模块,有两个实现类:

package com.unicom.network;

import com.lwy.it.InternetService;

public class BeijingUnicomNetwork implements InternetService {
    @Override
    public void connectInternet() {
        System.out.println("通过北京联通网络联网");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
package com.unicom.network;

import com.lwy.it.InternetService;

public class UnicomNetwork implements InternetService {
    @Override
    public void connectInternet() {
        System.out.println("通过联通网络联网");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注意:classpath下META-INF/service路径下com.lwy.it.InternetService文件

com.unicom.network.BeijingUnicomNetwork
com.unicom.network.UnicomNetwork
  • 1
  • 2

company模块中定义主方法:

package com.lwy.it;

import java.util.ServiceLoader;

public class Main {
    public static void main(String[] args) {
        // 使用ServiceLoader发现并加载服务
        ServiceLoader<InternetService> loader = ServiceLoader.load(InternetService.class);
        // 面向Service接口编程
        for (InternetService provider : loader) {
            provider.connectInternet();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

通过分别引入maven依赖不同,打印的结果也不同。

    <dependency>
        <groupId>com.lwy.it</groupId>
        <artifactId>unicom-network</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
    <dependency>
        <groupId>com.lwy.it</groupId>
        <artifactId>telecom-network</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/704069
推荐阅读
相关标签
  

闽ICP备14008679号