什么是jdk的spi?

前提概述

在面向对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可插拔的原则。再者硬编码的不好这处还在于:当原来的模块实现发生改变之后,依赖这个模块的功能代码必须进行调整修改。

SPI简介

  • spi 全称为(Service Provider Interface),是JDK内置的一种服务提供机制。
  • 这个是针对厂商或者插件的。
  • 一般来说对于未知的实现或者对扩展开放的系统,通常会把一些东西抽象出来,抽象的各个模块往往有很多不同的实现方案,例如:日志模块、xml解析模块、jdbc模块等。

SPI约定

  • 当服务的提供者,提供了服务接口的一种实现之后,在jar包中META-INF/services目录里同时创建一个以服务接口命名的文件。
  • 该文件里就是实现该服务接口的具体实现类(全称)。
  • 而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

应用场景

    1. common-logging 是apache最早提供的日志门面接口(只有接口,没有实现)。发现日志提供商是通过扫描META-INF/services/org.apache.commons.loggings.logging.LogFactory配置文件,通过读取该文件的内容找到日志提供商实现类。
    1. jdbc jdbc4基于spi的机制来发现驱动提供商,可以通过META-INF/services/java.sql.Driver文件里指定实现类的方式来暴露驱动提供者。

案例说明

在我们日常开发系统的过程中,日志收集、打印是一个不可缺少的功能模块。这里我实现一个简单的日志模块。

日志接口定义
package com.oneape.javaspi;
/**
 * described : 日志打印抽象类
 * Created by oneape on 2018-12-24 10:18.
 * Modify:
 */
public interface Log {
    void debug(String log);
    void info(String log);
}
日志接口实现1(Log4j方式)

Log4j.java类实现

package com.oneape.javaspi.log4j;

import com.oneape.javaspi.Log;

/**
 * described :
 * Created by oneape on 2018-12-24 10:19.
 * Modify:
 */
public class Log4j implements Log {

    public void debug(String log) {
        System.out.println("Log4j[debug]: --->" + log);
    }

    public void info(String log) {
        System.out.println("Log4j[info]: --->" + log);
    }
}

META-INF/services/com.oneape.javaspi.Log文件内容

com.oneape.javaspi.log4j.Log4j
日志接口实现2(Logback方式)

Logback.java类实现

package com.oneape.javaspi.logback;

import com.oneape.javaspi.Log;

/**
 * described :
 * Created by oneape on 2018-12-24 10:23.
 * Modify:
 */
public class Logback implements Log {
    public void debug(String log) {
        System.out.println("Logback[debug]: --->" + log);
    }

    public void info(String log) {
        System.out.println("Logback[info]: --->" + log);
    }
}

META-INF/services/com.oneape.javaspi.Log文件内容

com.oneape.javaspi.logback.Logback
外部程序调用方

调用方代码

package com.oneape.javaspi.use;

import com.oneape.javaspi.Log;

import java.util.Iterator;
import java.util.ServiceLoader;

/**
 * described :
 * Created by oneape on 2018-12-24 10:30.
 * Modify:
 */
public class Main {

    public static void main(String[] args) {
        System.out.println("---开始运行---");
        ServiceLoader serviceLoader = ServiceLoader.load(Log.class);
        Iterator iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            Log log = iterator.next();
            log.debug("开始使用日志");
            log.info("开始使用日志");
        }
        System.out.println("---运行结束---");
    }
}

pom.xml文件



    
        spi
        com.oneape
        1.0-SNAPSHOT
    
    4.0.0
    log-use

    
        1.8
    

    
        
            com.oneape
            log
            1.0-SNAPSHOT
        
        
            com.oneape
            log4j
            1.0-SNAPSHOT
        
    

最终运行结果如下:

---开始运行---
Log4j[debug]: --->开始使用日志
Log4j[info]: --->开始使用日志
---运行结束---

Process finished with exit code 0
小彩蛋

如果想要整个demo的源代码可以到github上下载
demo-java-spi

你可能感兴趣的:(什么是jdk的spi?)