Skip to content

Java Service Provider Interface (SPI) demo #65

Open
@Shellbye

Description

@Shellbye

JavaSPI是面向接口编程的典范,关于其意义和作用的分析,不是文本中重点,因此不做过多介绍,本文主要用于展示如何实际的构建并运行一个 demo.

项目模块结构

屏幕快照 2019-07-31 14 04 03

如上图所示,其中各个模块的作用分别如下:

spi-app

一个基于 Spring BootWeb工程,用于使用 SPI 提供的服务

spi-service

SPI 所提供的服务的接口,即定义

spi-service-provider-01

SPI 所提供的服务的一种具体实现

spi-service-provider-02

SPI 所提供的服务的另一种具体实现

服务的定义

首先是在spi-service中,有一个接口ContentService,提供一个内容,代码如下

package com.shellbye;

public interface ContentService {
    public String getContent();
}

服务的使用

其次是在spi-app中,对这个服务进行使用,首先需要添加依赖

        <dependency>
            <artifactId>spi-service</artifactId>
            <groupId>spi-demo-group</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

然后是具体的示例代码

package com.example.demo;

import com.shellbye.ContentService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;

@RestController
public class Controller {

    @GetMapping
    public String main() {
        System.out.println("enter");
        List<ContentService> services = new ArrayList<>();
        ServiceLoader<ContentService> loader = ServiceLoader.load(ContentService.class);

        loader.forEach(contentProvider -> {
            services.add(contentProvider);
            System.out.println(contentProvider.getContent());
        });
        return "OK";
    }
}

服务的实现

最后是服务的实现,由于两个实现基本一样,所以这里只展示一种。首先依然是需要添加依赖

        <dependency>
            <artifactId>spi-service</artifactId>
            <groupId>spi-demo-group</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

然后是具体的实现代码

package com.shellbye;

public class HelloContentService implements ContentService {
    @Override
    public String getContent() {
        return "Hello";
    }
}

这里有一些需要特殊操作的地方,就是根据约定,需要在resources中新建META-INF,然后在其中新建services,这个文件夹里需要以服务的接口的全限定名新建文件,文件里面的内容是具体的实现,比如文件名叫com.shellbye.ContentService,里面具体的内容如下

com.shellbye.HiContentService

这样,一个具体的实现就搞定了,另一个也是一样的。

最后

光是有上面的配置其实还是不够的,虽然根据网上看到的一些资料似乎是可以的,但是实际运行的时候还需要在spi-app添加对实现的依赖

        <dependency>
            <groupId>spi-demo-group</groupId>
            <artifactId>spi-service-provider-01</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>spi-demo-group</groupId>
            <artifactId>spi-service-provider-02</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

这个时候启动项目,在浏览器上访问 http://localhost:8080/,就会在项目的控制台看到如下输出

enter
Hello
Hi

本项目涉及到的代码在这里

参考

https://www.baeldung.com/java-spi

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions