0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Java中的SPI动态扩展(上)

jf_78858299 来源:码农参上 作者:Dr Hydra 2023-03-24 14:27 次阅读

八股文背多了,相信大家都听说过一个词, SPI扩展

有的面试官就很喜欢问这个问题,SpringBoot的自动装配是如何实现的?

基本上,你一说是基于spring的SPI扩展机制,再把spring.factories文件和EnableAutoConfiguration提一下,那么这个问题就答的八九不离十了。

就像四五年前,我去面试的时候被问到这个问题,SPI动态扩展机制这几个词从嘴里一说出来,就把面试官唬的一愣一愣的。可能他们也没见过这么能装逼的,一句话能简简单单说明白,非要拽一个听上去很高大上的词。

话说回来,被唬住的可不止是面试官,其实还有我自己。至于SPI扩展究竟是个啥,是怎么实现的,我当时也根本不明白。

不过现在的面试就是这样,对线八股文,要想唬住面试官,就得先唬住自己。

那么我们今天暂且不提spring的SPI扩展,先来看看java本身自带的SPI扩展机制是怎么一回事。

1、简介

SPI的全称是Service Provider Interface,翻译过来就是 服务提供者的接口 ,它所实现的其实是一种服务的发现机制。

这么说起来可能还是有点不好理解,我举个例子来类比一下。

在spring项目中,写service层代码前,会约定俗成的会添加一个接口层。然后通过spring中的依赖注入,可以借助@Autowired等方式注入这个接口的实现类的实例对象,之后对于service的调用一般也基于接口操作。

简单形容就是这样的:

图片

如图所示,接口、实现类都是由服务提供方提供,我们可以把controller看作服务调用者,调用方只管调用接口就可以了。

虽然也有声音认为,大部分情况下service只有一个实现类,接口层显得有些多余。但是在《Head First Design Patterns》这本书中,大佬们还是建议过:

Program to an interface, not an implementation.

没错,就是常说的 要面向接口编程 。至于好处,也不外乎是降低耦合度、方便日后扩展、提高了代码的灵活性和可维护性等等。

在上面这个例子里,这个接口层和其中的方法我们可以称之为 API ,而我们要讨论的SPI和它相比,有类似也有差异,还是先看图:

图片

简单来说,就是服务的调用方定义一个接口规范,可以由不同的服务提供者实现。并且,调用方能够通过某种机制来发现服务提供方,并通过接口调用它的能力。

通过对比,我们可以看出它们虽然都有着接口这一层面,但还是有很大的不同:

API中的接口是服务提供者给服务调用者的一个功能列表,而SPI中更多强调的是,服务调用者对服务实现的一种约束,服务提供者根据这种约束实现的服务,可以被服务调用者发现。

说白了,Java中的SPI实现的就是,你按我的接口规范实现服务,我就能通过某种机制为这个接口寻找到这个服务。

这么说起来可能还有些抽象,下面我们举一个例子,类比具体描述一下这个过程。

2、定义接口

说起智能家居系统,大家现在都比较熟悉了,只要是相同品牌下的产品,连上wifi就能够通过手机app控制了,非常方便。

虽然产品不断更新换代,型号更新层出不穷,但是同种家电在app上操作起来,功能一般都是一样的。就拿空调来说,我们在app上操作起来一般也就三个主要功能: 开关选模式调节温度

假设我现在在客厅、卧室、书房安装了3款不同型号的空调,并把它们都接入到了我app中,那么之后的操作都是相同的几个按键,简单粗暴。

图片

思考一下,无论是开关还是调温,都是通过app去调用设备的接口罢了,那么如果不同型号的空调各写各的接口,后端app在开发的时候光对接接口都麻烦的要死。

解决方法也很简单,我先定义一套接口规范,不管你以后什么型号的空调,都按我的规范来实现接口。以后只要我能发现你的设备,那么都可以按相同的方法来调用接口。

那么下面就先来定义这么一套接口规范,如果你以后想要接入智能家居系统,那么就要遵循这个规范来开发接口。

新建一个项目作为标准,就叫aircondition-standard好了,然后创建一个接口。除了3个操作以外,我们再添加一个获取空调型号的方法。

public interface IAircondition {
    // 获取型号
    String getType();
    
    // 开关
    void turnOnOff();

    // 调节温度
    void adjustTemperature(int temperature);

    // 模式变更
    void changeModel(int modelId);
}

这个接口后面要给服务的实现方来使用,用maven把它打成jar包:

mvn clean install

之后服务提供者在项目中就可以引入这个jar包了,有了这套规范,就保证了产品后期不管怎么更新换代,都能接入到系统来。

3、服务实现

制定并发布完规则后,挂式空调作为第一个服务提供者就来了,新建一个项目aircondition-hanging-type,并引入刚才打好的jar包:

<dependency>
    <groupId>com.cn.hydra<span class="hljs-name"groupId>
    <artifactId>aircondition-standard<span class="hljs-name"artifactId>
    <version>1.0-SNAPSHOT<span class="hljs-name"version>
<span class="hljs-name"dependency>

创建服务类,并实现前面定义的接口:

public class HangingTypeAircondition
        implements IAircondition{
    public String getType() {
        return "HangingType";
    }
    
    public void turnOnOff() {
        System.out.println("挂式空调开关");
    }

    public void adjustTemperature(int i) {
        System.out.println("挂式空调调节温度");
    }

    public void changeModel(int i) {
        System.out.println("挂式空调更换模式");
    }
}

在项目的resources的目录下,创建META-INF/services目录,然后以前面定义的接口名com.cn.hydra.IAircondition创建文件,并在文件中写入实现类的全限定名。

com.cn.hydra.HangingTypeAircondition

整个项目结构非常简单:

图片

这样,一个服务方的简单实现就搞定了,用maven打成jar包,之后就可以提供给调用方使用了。

同理,我们可以再创建一个立式空调的项目aircondition-vertical-type,也只创建一个服务类:

public class VerticalTypeAircondition
        implements IAircondition{
    public String getType() {
        return "VerticalType";
    }
    
    public void turnOnOff() {
        System.out.println("立式空调开关");
    }

    public void adjustTemperature(int i) {
        System.out.println("立式空调调节温度");
    }

    public void changeModel(int i) {
        System.out.println("立式空调更换模式");
    }
}

还是按上面的命名规则,创建一个配置文件:

com.cn.hydra.VerticalTypeAircondition

同样,打成jar包就完事了,至于服务调用者如何去发现和调用这两个服务,下面详细再说。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2954

    浏览量

    104510
  • SPI
    SPI
    +关注

    关注

    17

    文章

    1695

    浏览量

    91269
  • 代码
    +关注

    关注

    30

    文章

    4733

    浏览量

    68294
  • spring
    +关注

    关注

    0

    文章

    338

    浏览量

    14299
收藏 人收藏

    评论

    相关推荐

    JAVA操作英创主板SPI接口简介

    的个数,每一个SPITransfer需要用户自己实例化。  最后,使用完毕后关闭SPI设备:  spi.Close();5、SPI测试程序运行结果运行SPI传输
    发表于 10-20 13:16

    聊聊Dubbo - Dubbo可扩展机制实战

    是对Dubbo的扩展机制有一个基本的了解。如果对Java SPI比较了解的同学,可以跳过。Java SPI(Service Provider
    发表于 06-04 17:33

    嵌入式Linux系统内核抽象的动态扩展技术

    能下降。另外,微内核与传统的嵌入式Linux内核在结构是完全不同的。在嵌入式Linux,如果采用该技术来增加系统的动态扩展性能,需要对内核结构重新设计。  (2)可
    发表于 10-26 09:22

    嵌入式Linux系统内核抽象的动态扩展技术

    能下降。另外,微内核与传统的嵌入式Linux内核在结构是完全不同的。在嵌入式Linux,如果采用该技术来增加系统的动态扩展性能,需要对内核结构重新设计。  (2)可
    发表于 10-28 09:53

    嵌入式Linux系统内核抽象的动态扩展技术

    的切换和自陷次数增加,导致系统负载增加,系统性能下降。另外,微内核与传统的嵌入式Linux内核在结构是完全不同的。在嵌入式Linux,如果采用该技术来增加系统的动态扩展性能,需要对
    发表于 04-04 17:12

    java动态代理机制和作用

    的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java动态代理机制,所以本篇随笔就是对java动态机制进行一个回顾。 在
    发表于 09-27 14:37 0次下载

    java动态代理分析

    定义:为其他对象提供一种代理以控制对这个对象的访问。 动态代理使用 java动态代理机制以巧妙的方式实现了代理模式的设计理念。 代理模式示例代码 publicinterfaceSubject
    发表于 09-27 15:14 0次下载

    英创信息技术JAVA操作英创主板SPI接口简介

    2017年9月,英创在Linux的文件系统移植了针对嵌入式Linux的JRE(Java Runtime Environment),能够支持Java应用程序的运行。由于Java语言不能
    的头像 发表于 02-06 11:09 1872次阅读
    英创信息技术<b class='flag-5'>JAVA</b>操作英创主板<b class='flag-5'>SPI</b>接口简介

    Java实验:类和对象的扩展

    Java实验:类和对象的扩展
    发表于 07-08 15:36 20次下载
    <b class='flag-5'>Java</b>实验:类和对象的<b class='flag-5'>扩展</b>

    源码级深度理解Java SPI

    SPI 配置:Java SPI 机制约定的配置文件,提供查找服务实现类的逻辑。配置文件必须置于 META-INF/services 目录,并且,文件名应与服务提供者接口的完全限定名保
    的头像 发表于 11-15 11:38 634次阅读

    基于spring的SPI扩展机制是如何实现的?

    基本,你一说是基于 spring 的 SPI 扩展机制,再把spring.factories文件和EnableAutoConfiguration提一下,那么这个问题就答的八九不离十了。
    的头像 发表于 03-07 09:17 994次阅读

    JavaSPI动态扩展(下)

    基本,你一说是基于spring的SPI扩展机制,再把`spring.factories`文件和`EnableAutoConfiguration`提一下,那么这个问题就答的八九不离十了。
    的头像 发表于 03-24 14:27 529次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>中</b>的<b class='flag-5'>SPI</b><b class='flag-5'>动态</b><b class='flag-5'>扩展</b>(下)

    如何保证Java程序内存密码的安全

    开发和构建简单。基于 SPI 的纯 Java 编程模型,一键式构建,将 Java 机密计算开发构建门槛一降到底。
    发表于 04-20 12:49 907次阅读

    SPI是什么?Java SPI的使用介绍

    SPI 全称 Service Provider Interface,是 Java 提供的一套用来被第三方实现或者扩展的 API,它可以用来启用框架扩展和替换组件。
    的头像 发表于 09-02 09:58 1335次阅读
    <b class='flag-5'>SPI</b>是什么?<b class='flag-5'>Java</b> <b class='flag-5'>SPI</b>的使用介绍

    java本身自带的SPI扩展机制是怎么一回事?

    八股文背多了,相信大家都听说过一个词,SPI 扩展
    的头像 发表于 01-02 10:32 646次阅读
    <b class='flag-5'>java</b>本身自带的<b class='flag-5'>SPI</b><b class='flag-5'>扩展</b>机制是怎么一回事?