SPI服务

作者: ZMRWEGo | 来源:发表于2019-03-24 14:35 被阅读0次

    简介

    SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的 SPI 机制,而是对其进行了增强,使其能够更好的满足需求。在 Dubbo 中,SPI 是一个非常重要的模块。基于 SPI,我们可以很容易的对 Dubbo 进行拓展。如果大家想要学习 Dubbo 的源码,SPI 机制务必弄懂。接下来,我们先来了解一下 Java SPI 与 Dubbo SPI 的用法,然后再来分析 Dubbo SPI 的源码。

    SPI示例

    1. javaSPI示例

    关于java spi的具体实现机制,可以查看这篇博文

    jdk spi逐行加载实现类 放入缓存

    2. dubbo SPI实例

    dubbo的SPI与java的基本相同,但是它的loader不在继承自Iterable接口,它通过getExtension("xx")方法获取指定的实现类。

    • Dubbo的IOC机制
      我们知道要实例化一个类时,需要依次实例化该类的所有实现类,那么dubbo怎么做到进行依赖类的实例化呢?Dubbo 首先会通过反射获取到实例的所有方法,然后再遍历方法列表,检测方法名是否具有 setter 方法特征。若有,则通过 ObjectFactory 获取依赖对象,最后通过反射调用 setter 方法将依赖设置到目标对象中
      这里我们稍微分析一下源码:
    private T injectExtension(T instance) {
        try {
            if (objectFactory != null) {
                // 遍历目标类的所有方法
                for (Method method : instance.getClass().getMethods()) {
                    // 检测方法是否以 set 开头,且方法仅有一个参数,且方法访问级别为 public
                    if (method.getName().startsWith("set")
                        && method.getParameterTypes().length == 1
                        && Modifier.isPublic(method.getModifiers())) {
                        // 获取 setter 方法参数类型
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            // 获取属性名,比如 setName 方法对应属性名 name
                            String property = method.getName().length() > 3 ? 
                                method.getName().substring(3, 4).toLowerCase() + 
                                    method.getName().substring(4) : "";
                            // 从 ObjectFactory 中获取依赖对象
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                // 通过反射调用 setter 方法设置依赖
                                method.invoke(instance, object);
                            }
                        } catch (Exception e) {
                            logger.error("fail to inject via method...");
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
    }
    

    3. dubbo SPI与jdk SPI的区别

    jdk SPI只能一次性的执行配置文件中的所有实现类,而dubbo SPI则可以根据指定的类名执行对应的方法。
    dubbo SPI增加了对IOC和AOP的支持,一个扩展点可以通过setter方法注入其他扩展点

    相关文章

      网友评论

          本文标题:SPI服务

          本文链接:https://www.haomeiwen.com/subject/nwblvqtx.html