SPI入门学习


title: SPI
tags: JDK,SPI,服务发现
grammar_cjkRuby: true


什么是SPI

SPI,JDK内置的一种服务提供发现机制,简单来说,就是一种动态替换机制。比如说,定义了一种规范,需要厂商去实现。对于应用方来说,只需将对应厂商的实现集成进来,就可以实现对该规范的实现,是一种插拔式的拓展手段。

为什么需要SPI

在面向对象的设计中,一般基于接口编程,模块之间不会对实现类进行硬编码,一旦涉及某一个实现类,需要动态指定或者修改该实现类,就要修改代码,就违反了可插拔的原则。而SPI的出现,弥补了这种问题。具体实现在模块之间无需动态指定,只需传进对应接口类型,就可以动态找到对应的实现类

如何实现SPI

SPI实现需要遵循以下规范:

  • 需要在classpath路径创建一个文件夹,名为META-INF/services
  • 需要在META-INF/services创建一个文件:
    • 文件名为该接口的全路径名称
    • 文件内容为该接口实现类的全路径
    • 文件编码必须是UTF-8
  • 通过java.util.ServiceLoader加载机制来获取

SPI实践

定义接口

public interface DataBaseDriver {

    String connect(String host);
}

实现接口

package com.lung.spi.mysql;

import com.lung.spi.api.DataBaseDriver;

/**
 * @Author: liumenglong
 * @Date: 2018/9/3 10:31
 * @Description:
 */
public class MysqlDriver implements DataBaseDriver {
    public String connect(String s) {
        return "Mysql Driver : "+s;
    }
}

配置文件

1539239079579.png
1539239101366.png

发现服务

1539239162411.png

SPI的优点和缺点

优点:
使用Java SPI机制的优势是实现解耦,使得第三方服务模块的装配控制的逻辑与调用者的业务代码分离,而不是耦合在一起。应用程序可以根据实际业务情况启用框架扩展或替换框架组件。
缺点:
虽然ServiceLoader也算是使用的延迟加载,但是基本只能通过遍历全部获取,也就是接口的实现类全部加载并实例化一遍。如果你并不想用某些实现类,它也被加载并实例化了,这就造成了浪费。获取某个实现类的方式不够灵活,只能通过Iterator形式获取,不能根据某个参数来获取对应的实现类。
多个并发多线程使用ServiceLoader类的实例是不安全的。

参考

理解的Java中SPI机制

你可能感兴趣的:(SPI入门学习)