Java SPI 总结

Java SPI 总结

1. Java SPI 目标

  1. 定义好SPI, 方便三方定制扩展, 如JDBC的驱动实现, Dubbo的SPI实现.
  2. 原生, 脱离Spring等容器框架, 动态加载接口的实现.

2. SPI vs API

  • API (Application Programming Interface)

    面向 使用者

  • SPI (Service Provider Interface)

    面向 扩展者

3. Java SPI 使用

  1. 定义接口 demo.java.spi.DemoSpi

    package demo.java.spi;
    
    public interface DemoSpi {
        void helloSpi();
    }
    
  2. 定义实现 demo.java.spi.impl.DemoSpiImpl(V1,V2)

    package demo.java.spi.impl;
    
    import demo.java.spi.DemoSpi;
    
    public class DemoSpiV1Impl implements DemoSpi {
        public DemoSpiV1Impl() {
            System.out.println("DemoSpiV1Impl初始化...");
        }
    
        @Override
        public void helloSpi() {
            System.out.println("hello spi v1");
        }
    }
    
    public class DemoSpiV2Impl implements DemoSpi {
        public DemoSpiV2Impl() {
            System.out.println("DemoSpiV2Impl初始化...");
        }
    
        @Override
        public void helloSpi() {
            System.out.println("hello spi v2");
        }
    }
    
  3. 新建resources/META-INF/services/demo.java.spi.DemoSpi

    demo.java.spi.impl.DemoSpiV1Impl
    demo.java.spi.impl.DemoSpiV2Impl
    
  4. demo.java.spi.DemoSpiTest

    package demo.java.spi;
    
    import java.util.Iterator;
    import java.util.ServiceLoader;
    
    public class DemoSpiTest {
    
        public static void main(String[] args) {
            ServiceLoader<DemoSpi> serviceLoader = ServiceLoader.load(DemoSpi.class);
    
            /**
             * 遍历方式1, 等价于方式2, 但是便于调试
             *
             * 1. (懒加载方式) 只有获取时, 才会
             *     - 解析配置文件, 获取SPI接口的实现类名
             *     - Class.forName加载实现类
             *     - 反射生成实例对象
             *
             * 2. 且有缓存, 多次遍历, 只有第一次, 才会初始化实例对象
             */
            Iterator<DemoSpi> iterator = serviceLoader.iterator();
            while(iterator.hasNext()) {
                DemoSpi demoSpi = iterator.next();
                demoSpi.helloSpi();
            }
    
            System.out.println("---------------");
    
            // 遍历方式2
            for (DemoSpi demoSpi : serviceLoader) {
                demoSpi.helloSpi();
            }
        }
    }
    
  5. 运行结果

    DemoSpiV1Impl初始化...
    hello spi v1
    DemoSpiV2Impl初始化...
    hello spi v2
    ---------------
    hello spi v1
    hello spi v2
    

4. Java SPI 原理

  1. (懒加载方式) 只有获取时, 才会

    • 解析配置文件, 获取SPI接口的实现类名
    • Class.forName加载实现类
    • 反射生成实例对象
  2. 且有缓存, 多次遍历, 只有第一次, 才会初始化实例对象

5. 参考

  1. Oracle SPI Tutorial
  2. Java SPI详解
  3. 深入理解java SPI机制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值