zoukankan      html  css  js  c++  java
  • 聊聊Java SPI机制

    一、Java SPI机制

    SPI(Service Provider Interface)是JDK内置的服务发现机制,用在不同模块间通过接口调用服务,避免对具体服务服务接口具体实现类的耦合。比如JDBC的数据库驱动模块,不同数据库连接驱动接口相同但实现类不同,在使用SPI机制以前调用驱动代码需要直接在类里采用Class.forName(具体实现类全名)的方式调用,这样调用方依赖了具体的驱动实现,在替换驱动实现时要修改代码。而采用SPI机制后,在驱动jar包的META-INF/services下面新建一个驱动接口全名的UTF-8编码的文件,里面写上具体实现类的全名,这样调用方通过Java 的ServiceLoad接口动态的去加载接口的实现类,从而达到替换驱动实现不用修改代码的效果,如下代码:

     public static void main(String[] args) {
            ServiceLoader<DriverService> serviceLoader = ServiceLoader.load(DriverService.class);
            for (DriverService driverService: serviceLoader){
                System.out.println(driverService.getName());
            }
        }

    使用步骤:

    1、服务调用方通过ServiceLoader.load加载服务接口的实现类实例;

    2、服务提供方实现服务接口后,在自己Jar包的META-INF/services目录下新建一个接口名全名的文件,并将具体实现类全名写入。

    二、Spring SPI机制

     很多开源框架库里都直接或间接使用了Java 的SPI机制。比如Spring就有类似的SPI机制,通过SpringFactoriesLoader代替JDK中ServiceLoader,通过META-INF/spring.factories文件代替META-INF/service目录下的描述文件,具体实现步骤不同,但原理都是使用Java 的反射机制。

    public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
            Assert.notNull(factoryClass, "'factoryClass' must not be null");
            ClassLoader classLoaderToUse = classLoader;
            if (classLoaderToUse == null) {
                classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
            }
            List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
            if (logger.isTraceEnabled()) {
                logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
            }
            List<T> result = new ArrayList<>(factoryNames.size());
            for (String factoryName : factoryNames) {
                result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
            }
            AnnotationAwareOrderComparator.sort(result);
            return result;
        }

    spring boot读取properties文件spring.factories

    三、Dubbo的SPI扩展

    dubbo的扩展机制和java的SPI机制非常相似,但是又增加了如下功能:

    1 可以方便的获取某一个想要的扩展实现,java的SPI机制就没有提供这样的功能

    2 对于扩展实现IOC依赖注入功能:

    举例来说:接口A,实现者A1、A2。接口B,实现者B1、B2。

    现在实现者A1含有setB()方法,会自动注入一个接口B的实现者,此时注入B1还是B2呢?都不是,而是注入一个动态生成的接口B的实现者B$Adpative,该实现者能够根据参数的不同,自动引用B1或者B2来完成相应的功能

    3 对扩展采用装饰器模式进行功能增强,类似AOP实现的功能

    跟我学Dubbo系列之Java SPI机制简介

  • 相关阅读:
    testd3p
    my open音频的
    1
    one play
    ndk ffmpeg实践2
    ndk ffmpeg实践
    Mac ndk21 交叉ffmpeg目前
    ffmpeg交叉
    and cmake 链接库及播放例子 及读文件
    更正之前《登录小案例》密码错3次15分钟内不准登录
  • 原文地址:https://www.cnblogs.com/doit8791/p/8871832.html
Copyright © 2011-2022 走看看