Java中的SPI扩展机制(有demo)

参考连接:https://www.jianshu.com/p/3a3edbcd8f24

一、什么是SPI

SPI ,全称为 Service Provider Interface,是一种服务发现机制。它通过在ClassPath路径下的META-INF/services文件夹查找文件,自动加载文件里所定义的类。

二、设计的目的

肯定是为了扩展性,在不想修改源码的情况下,去替换系统原有的实现,代价最小也最灵活。

三、案例demo

先看看目录接结构

  • spi-api模块:定义扩展接口
  • spi-client模块:扩展的模块
  • spi-test模块:测试模块

github地址:https://github.com/XiaoBinNumberOne/java-spi-demo

四、源码分析

首先看看ServiceLoader.java类结构

ServiceLoader.load,load方法创建了一些属性,重要的是实例化了内部类,LazyIterator。最后返回ServiceLoader的实例。

public final class ServiceLoader<S> implements Iterable<S>
    private ServiceLoader(Class<S> svc, ClassLoader cl) {
        //要加载的接口
        service = Objects.requireNonNull(svc, "Service interface cannot be null");
        //类加载器
        loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
        //访问控制器
        acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
        //先清空
        providers.clear();
        //实例化内部类
        LazyIterator lookupIterator = new LazyIterator(service, loader);
    }
}

查找实现类和创建实现类的过程,都在LazyIterator完成。当我们调用iterator.hasNext和iterator.next方法的时候,实际上调用的都是LazyIterator的相应方法。

public Iterator<S> iterator() {
    return new Iterator<S>() {
        public boolean hasNext() {
            return lookupIterator.hasNext();
        }
        public S next() {
            return lookupIterator.next();
        }
        .......
    };
}

所以,我们重点关注lookupIterator.hasNext()方法,它最终会调用到hasNextService。

private class LazyIterator implements Iterator<S>{
    Class<S> service;
    ClassLoader loader;
    Enumeration<URL> configs = null;
    Iterator<String> pending = null;
    String nextName = null;
    private boolean hasNextService() {
        //第二次调用的时候,已经解析完成了,直接返回
        if (nextName != null) {
            return true;
        }
        if (configs == null) {
            //META-INF/services/ 加上接口的全限定类名,就是文件服务类的文件
            //META-INF/services/com.viewscenes.netsupervisor.spi.SPIService
            String fullName = PREFIX + service.getName();
            //将文件路径转成URL对象
            configs = loader.getResources(fullName);
        }
        while ((pending == null) || !pending.hasNext()) {
            //解析URL文件对象,读取内容,最后返回
            pending = parse(service, configs.nextElement());
        }
        //拿到第一个实现类的类名
        nextName = pending.next();
        return true;
    }
}
分享学习是一件开心事

原文地址:https://www.cnblogs.com/hy-xiaobin/p/12204849.html

时间: 2024-11-10 13:28:17

Java中的SPI扩展机制(有demo)的相关文章

Dubbo中SPI扩展机制解析

dubbo的SPI机制类似与Java的SPI,Java的SPI会一次性的实例化所有扩展点的实现,有点显得浪费资源. dubbo的扩展机制可以方便的获取某一个想要的扩展实现,每个实现都有自己的name,可以通过name找到具体的实现. 每个扩展点都有一个@Adaptive实例,用来注入到依赖这个扩展点的某些类中,运行时通过url参数去动态判断最终选择哪个Extension实例用. dubbo的SPI扩展机制增加了对扩展点自动装配(类似IOC)和自动包装(类似AOP)的支持. 标注了@Activat

Java中的内存处理机制和final、static、final static总结

Java中的内存处理机制和final.static.final static总结 装载自:http://blog.csdn.net/wqthaha/article/details/20923579 Java程序运行在JVM上,可以把JVM理解成Java程序和操作系统之间的桥梁,JVM实现了Java的平台无关性,由此可见JVM的重要性.所以在学习Java内存分配原理的时候一定要牢记这一切都是在JVM中进行的,JVM是内存分配原理的基础与前提.         一个完整的Java程序运行过程会涉及以

Java中的内存分配机制

Java的内存分为两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型变量和对象的引用都在函数的栈内存中分配.当在一个代码块中定义一个变量的时候,java就在栈中为其分配内存,当超过作用域的时候内存自动释放. 对内存用来存放new创建的对象和数组.在堆中分配的内存,由java虚拟机的垃圾回收机器管理.java的堆是运行时数据区,堆的优势是可以动态的分配内存大小,生存周期也不必事先告诉编译器,但是,由于是动态分配,存取速度慢. 栈的优势是比堆的存取速度快,仅次于寄存器,栈数据可以共享,但

Java中实现多态的机制

一,多态定义: 多态就是指一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定. 一,实现多态的机制 java中实现多态的机制是依靠父类或接口的引用指向子类.从而实现了一个对象多种形态的特性.其中父类的引用是在程序运行时动态的指向具体的实例,调用该引用的方法时,不是根据引用变量的类型中定义的方法来运行,而是根据具体的实例的方法. 三,条件 Java实现多态有三个必要条件:继承.重写.向上转型 原文地址:https://www.cn

Java 中的等待唤醒机制透彻讲解

线程的状态 首先了解一下什么是线程的状态,线程状态就是当线程被创建(new),并且启动(start)后,它不是一启动就进入了执行状态(run),也不是一直都处于执行状态. 这里说一下Java 的Thread类里面有一个State方法,这个方法里面涵盖了6种线程的状态,如下: public enum State { // 尚未启动的线程的线程状态. NEW, // 可运行线程的线程状态. RUNNABLE, // 线程的线程状态被阻塞,等待监视器锁定. BLOCKED, // 等待线程的线程状态.

理解 Dubbo SPI 扩展机制

写在前面 最近接触了 gRPC 体会到虽然众多 RPC 框架各有各的特点但是他们提供的特性和功能有很多的相似之处 , 这就说明他们面对同样的分布式系统带来的问题.从 2016 年左右开始接触到 dubbo ,基本停留在使用的层面,对 dubbo 的设计以及着重要解决的问题都没有系统的研究过,通过对 dubbo 和其他类似 RPC 产品的系统学习 ,学习分布式系统中面临的共同问题以及解决之道. 微内核架构 微内核架构 (Microkernel architecture) 模式也被称为插件架构 (P

深入Java核心 Java中多态的实现机制(1)

多态性是Java面向对象的一个重要机制,本文将向您详细介绍Java语言中多态性的实现原理和方法,通过多态一点带出更多Java面向对象有趣而实用的知识. 多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次深入Java核心,一起学习Java中多态性的实现. “polymorphism(多态)”一词来自希腊语,意为“多种形式”.多数Java程序员把多态看

java中存在垃圾回收机制,但是还会有内存泄漏的问题,原因是

答案是肯定的,但不能拿这一句回答面试官的问题.分析:JAVA是支持垃圾回收机制的,在这样的一个背景下,内存泄露又被称为"无意识的对象保持".如果一个对象引用被无意识地保留下来,那么垃圾回收器不仅不会处理这个对象,而且也不处理被这个对象引用的其它对象."内存泄露"就是内存中某些内存不可被回收. 举个例子:如果对一个栈(Stack类)先是进行入栈操作,之后再进行出栈操作,那么弹出来的对象将不会被当做垃圾回收,即使使用栈的客户程序不再引用这些对象,因为栈内部存在着对这些已

java中实现多态的机制是什么?

多态性是面向对象程序设计代码重用的一个重要机制,我们曾不只一次的提到Java多态性.在Java运行时多态性:继承和接口的实现一文中,我们曾详细介绍了Java实现运行时多态性的动态方法调度:今天我们再次深入Java核心,一起学习Java中多态性的实现. “polymorphism(多态)”一词来自希腊语,意为“多种形式”.多数Java程序员把多态看作对象的一种能力,使其能调用正确的方法版本.尽管如此,这种面向实现的观点导致了多态的神奇功能,胜于仅仅把多态看成纯粹的概念. Java中的多态总是子类型