Skip to content

Java Service Provider Interface (SPI) demo #65

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Shellbye opened this issue Jul 31, 2019 · 0 comments
Open

Java Service Provider Interface (SPI) demo #65

Shellbye opened this issue Jul 31, 2019 · 0 comments

Comments

@Shellbye
Copy link
Owner

Shellbye commented Jul 31, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant