zoukankan      html  css  js  c++  java
  • Java基础系列-SPI你认识吗

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755313.html

    一、SPI是什么

    SPI是相对API而言的。

    API指的是应用对服务调用方提供的接口,用于提供某种服务、功能,面向的是服务调用方。

    SPI指的是应用对服务实现方提供的接口,用于实现某种服务、功能,面向的是服务实现方

    二、SPI的使用

    2.1 第一步:创建服务接口

    package com.dh.spi;
    
    public interface Fruit {
        String getName();
    }
    

    2.2 第二步:创建多个服务实现

    package com.dh.spi;
    
    public class Apple implements Fruit {
        @Override
        public String getName() {
            return "apple";
        }
    }
    
    package com.dh.spi;
    
    public class Banana implements Fruit {
        @Override
        public String getName() {
            return "Banana";
        }
    }
    

    这里的两个服务实现类,针对的是两个服务实现方,一方实现了Apple,另一方实现了Banana。

    2.3 第三步:创建配置文件

    在resource下创建/META-INF/services目录,在services目录下创建以服务接口全限定名为名称的文件:com.dh.spi.Fruit

    文件内容为,当前服务实现的服务实现者类的全限定名

    com.dh.spi.Apple
    

    2.4 第四步:创建测试类

    public class Test {
        public static void main(String[] args) {
            ServiceLoader<Fruit> s = ServiceLoader.load(Fruit.class);
            Iterator<Fruit> it = s.iterator();
            while(it.hasNext())
                System.out.println(it.next().getName());
        }
    }
    

    执行结果为:

    apple
    

    三、SPI的实现原理

    SPI的实现主要依靠的就是ServiceLoader类。使用该类加载接口类型(例如:Fruit.class)

    ServiceLoader<Fruit> s = ServiceLoader.load(Fruit.class);
    

    虽然是一个load方法,但是并没有加载到指定的服务实现类,这里仅仅是对加载服务实现类做一些准备工作:

    • 创建ServiceLoader
    • 为service赋值
    • 为loader赋值
    • 为acc赋值
    • 清空providers缓存
    • 为lookupIterator赋值,其实就是创建一个LazyIterator延迟迭代器。

    然后创建迭代器:

    Iterator<Fruit> it = s.iterator();
    

    iterator方法中采用了匿名内部类的方式定义了一个新的迭代器,这个迭代器中每一个方法都是通过调用之前创建好的延迟迭代器lookupIterator来完成的

    最后就是进行迭代加载了。

    while(it.hasNext())
        System.out.println(it.next().getName());
    

    hasNext方法调用了延迟迭代器的hasNext方法,内部调用了hasNextService方法,在这个方法中就会设法去找到指定名称(META-INF/services/+接口全限定名)的资源文件。并完成读取文件内容的操作。

    然后执行it.next()操作,这个又会调用延迟迭代器的对应方法hasNext,内部调用了nextService方法,这个方法主要功能就是加载上面从文件中读取到的全限定名称表示的类。并生成实例,将实例保存到providers中。

    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
    
  • 相关阅读:
    线程池中shutdown()和shutdownNow()方法的区别
    java.util.concurrent.TimeoutException: Idle timeout expired: 300000/300000 ms
    ConnectTimeout和ReadTimeout所代表的意义
    hive 查询注意问题
    java面试题之int和Integer的区别
    MySQL中KEY、PRIMARY KEY、UNIQUE KEY、INDEX 的区别
    MySQL数据库使用mysqldump导出数据详解
    C++宏定义详解
    OTL调用存储过程/函数及注意事项
    linux自定义开机启动服务和chkconfig使用方法
  • 原文地址:https://www.cnblogs.com/V1haoge/p/10755313.html
Copyright © 2011-2022 走看看