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<>();
    
  • 相关阅读:
    DataTable进行排序Asc升序,Desc降序
    Money型字段小数点后保留两位小数
    删除RHSA文件方法
    PowerDesigner 同名问题解决 Entity Attribute name uniqueness
    Repeater嵌套绑定Repeater以及内层调用外层数据
    让A超链接无效的办法 阻止元素发生默认的行为
    图的遍历
    Modular Production Line
    网络流24题-最长k可重区间集问题
    运输计划
  • 原文地址:https://www.cnblogs.com/V1haoge/p/10755313.html
Copyright © 2011-2022 走看看