zoukankan      html  css  js  c++  java
  • Java_SPI思想

    研究SpringBoot源码的时候偶遇SpringFactoriesLoader,即SPI思想(也可以说是一种SPI机制)

    1、SPI 思想是什么?

    SPI 的全名为 Service Provider Interface 。SPI 思想 也可以叫做 SPI机制 ,它就是为某个接口寻找服务实现的机制

    2、为什么会有这个东西?

    ​ 这个东西主要微服务用的多,因为这个思想是针对厂商或者插件的。在java.util.ServiceLoader 的API文档里有比较详细的介绍。

    ​ 简单的总结下 Java SPI 机制的思想。我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则,如果需要替换一种实现,就需要修改代码。

    ​ 为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI 就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外(通过约定的配置文件),在模块化设计中这个机制尤其重要。

    ​ 同时起到解耦的作用。

    3、SPI 具体怎么实现呢?

    ​ 为了使用Java SPI ,需要遵循一种约定,该约定为: 当服务的提供者(厂商或者插件),提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口全类名命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

    4、话不多说,代码走起

    4.1、支付案例

    一个订单系统有一个支付模块,是基于接口编程的。支付的实现可能是基于支付宝支付、也可以基于微信支付等等

    建立一个maven项目:父项目 java-spi、子项目(包含四个模块) main-pay、services-common、wx-pay、zfb-pay

    img

    各个模块细节:

    http://note.youdao.com/yws/public/resource/4a3ed872ace93dc1115e9af8c1dd1aba/xmlnote/4CE2A5659721477692BC6E0A0A3217B3/15506

    服务接口定义:

    package com.xd.service;
    
    /**
     * @author dee
     * @create 2020-11-19 0:59
     */
    public interface PayService {
        public void pay();
    }
    

    微信厂商实现模块:

    package com.xd.impl;
    
    import com.xd.service.PayService;
    
    /**
     * @author dee
     * @create 2020-11-19 1:15
     */
    public class WxPayService implements PayService {
        @Override
        public void pay() {
            System.out.println("微信支付!");
        }
    }
    

    支付宝厂商实现模块:

    package com.xd.impl;
    
    import com.xd.service.PayService;
    
    /**
     * @author dee
     * @create 2020-11-19 1:01
     */
    public class ZfbPayService implements PayService {
        @Override
        public void pay() {
            System.out.println("支付宝支付!");
        }
    }
    

    主程序模块:

    package com.xd;
    
    import com.xd.impl.WxPayService;
    import com.xd.service.PayService;
    
    import java.util.Iterator;
    import java.util.ServiceLoader;
    
    /**
     * @author dee
     * @create 2020-11-19 1:17
     */
    public class PayTest {
    
        public static void main(String[] args) {
            //通过load方法新建对象
            ServiceLoader<PayService> serviceLoader = ServiceLoader.load(PayService.class);
            
            Iterator<PayService> iterator = serviceLoader.iterator();
            while (iterator.hasNext()){
                PayService payService = iterator.next();
                payService.pay();
            }
        }
    }
    

    当需要使用微信支付的时候,只需要在主程序pom文件导入微信模块的pom依赖即可

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>wx-pay</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    

    需要注意的是:厂商接口实现模块,有一个路径为META-INF/services/文件名为 com.xd.service.PayService的文件,里面内容为微信实现类的全类名,即SPI约定

    com.xd.impl.WxPayService
    

    执行主程序输出:

    微信支付!
    

    当需要使用支付宝支付只需要导入支付宝实现模块pom依赖即可

    <dependency>
        <groupId>org.example</groupId>
        <artifactId>zfb-pay</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
    

    执行主程序输出:

    支付宝支付!
    

    下面这些技术也有使用SPI思想,这里就不在这里扩展了!

    4.2、DriverManager

    DriverManager是jdbc里管理和注册不同数据库driver的工具类。

    4.3、Spring

    Spring中运用到spi思想的地方也有很多,下面随便列举几个

    scan、scop、ConfigurableBeanFactory

    4.4、SPI思想可是SpringBoot的灵魂

    SpringFactoriesLoader工具类

    4.5、Hotspot

    参考资料:

    https://zhuanlan.zhihu.com/p/28909673

    https://blog.csdn.net/sigangjun/article/details/79071850?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2.not_use_machine_learn_pai

    https://www.bilibili.com/video/BV13A411B7JH?from=search&seid=17307742882483866414

  • 相关阅读:
    一张图带你了解数据分析的完整流程,建议收藏
    【Unnatural × Lemon × 武汉】如果病毒结束了,你最想干什么事
    两万字深度介绍分布式系统原理!【收藏版】
    ETL的基础知识,看完你就全明白了!
    Java最大不重复子串
    一文速懂利用python字典的引用传递实现循环套娃(嵌套)
    ETSI GS MEC 015,MEP 带宽管理 API
    laravel 5.5 ajax返回错误信息
    laravel 5.5 ajax返回错误信息
    从实践出发:微服务布道师告诉你Spring Cloud与Boot他如何选择
  • 原文地址:https://www.cnblogs.com/king-of-purple/p/14013067.html
Copyright © 2011-2022 走看看