JAVA SPI机制

霸气de小男生 提交于 2020-08-08 13:31:58

SPI机制


@Author:zxw

@school:吉首大学

参考资料:http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html


1. 前言

2. JAVA SPI

  ServiceLoader<Robot> loader = ServiceLoader.load(Robot.class);
  System.out.println("JAVA SPI");
  loader.forEach(Robot::sayHello);

创建一个Iteraotor.iterator方法(),并创建一个接口

public S next() {
    if (knownProviders.hasNext())
        return knownProviders.next().getValue();
    return lookupIterator.next();
}

首先通过next()方法获取下一元素

public S next() {
            if (acc == null) {
                // 进入这
                return nextService();
            } else {
                PrivilegedAction<S> action = new PrivilegedAction<S>() {
                    public S run() { return nextService(); }
                };
                return AccessController.doPrivileged(action, acc);
            }
        }
private S nextService() {
    		// 判断是否有service
            if (!hasNextService())
                throw new NoSuchElementException();
            String cn = nextName;
            nextName = null;
            Class<?> c = null;
            try {
                // 通过forName以及类的全限定名称加载
                c = Class.forName(cn, false, loader);
            } catch (ClassNotFoundException x) {
                fail(service,
                     "Provider " + cn + " not found");
            }
            if (!service.isAssignableFrom(c)) {
                fail(service,
                     "Provider " + cn  + " not a subtype");
            }
            try {
                S p = service.cast(c.newInstance());
                providers.put(cn, p);
                return p;
            } catch (Throwable x) {
                fail(service,
                     "Provider " + cn + " could not be instantiated",
                     x);
            }
            throw new Error();          // This cannot happen
        }
 private boolean hasNextService() {
     		// 实现类名
            if (nextName != null) {
                return true;
            }
            if (configs == null) {
                try {
                    String fullName = PREFIX + service.getName();
                    if (loader == null)
                        configs = ClassLoader.getSystemResources(fullName);
                    else
                        configs = loader.getResources(fullName);
                } catch (IOException x) {
                    fail(service, "Error locating configuration files", x);
                }
            }
            while ((pending == null) || !pending.hasNext()) {
                if (!configs.hasMoreElements()) {
                    return false;
                }
                pending = parse(service, configs.nextElement());
            }
            nextName = pending.next();
            return true;
        }

3. Dubbo SPI

 @Test
    public void dubboHello() {
        ExtensionLoader<Robot> extensionLoader = ExtensionLoader.getExtensionLoader(Robot.class);
        Robot optimusPrime = extensionLoader.getExtension("optimusPrime");
        optimusPrime.sayHello();
        System.out.println("------");
        Robot bumblebee = extensionLoader.getExtension("bumblebee");
        bumblebee.sayHello();
    }

现在看看extensionLoader.getExtension方法中做了些什么。

   public T getExtension(String name) {
       // 判断名称是否为空
        if (StringUtils.isEmpty(name)) {
            // 抛出异常
            throw new IllegalArgumentException("Extension name == null");
        }
       // 如果为ture,则获取默认扩展实现类
        if ("true".equals(name)) {
            return getDefaultExtension();
        }
       // 如果不存在,则添加进缓存实例map中
       // 持有目标对象
        final Holder<Object> holder = getOrCreateHolder(name);
        Object instance = holder.get();
       // 判断holder的值是否为空,如果为空则进行设置
       // 双重检查
        if (instance == null) {
            synchronized (holder) {
                instance = holder.get();
                if (instance == null) {
                    // 创建拓展实例
                    instance = createExtension(name);
                    // 设置实例到holder中
                    holder.set(instance);
                }
            }
        }
        return (T) instance;
    }

3.1 getDefaultExtension()

private Holder<Object> getOrCreateHolder(String name) {
        Holder<Object> holder = cachedInstances.get(name);
        if (holder == null) {
            /**
            * if (!map.containsKey(key))
     		*   return map.put(key, value);
     		* else
     		* 	return map.get(key);
            */
            // 创建一个Holder类(用于保存值)
            cachedInstances.putIfAbsent(name, new Holder<>());
            holder = cachedInstances.get(name);
        }
        return holder;
    }

3.2 getOrCreateHolder()

private Holder<Object> getOrCreateHolder(String name) {
        Holder<Object> holder = cachedInstances.get(name);
        if (holder == null) {
            /**
            * if (!map.containsKey(key))
     		*   return map.put(key, value);
     		* else
     		* 	return map.get(key);
            */
            // 创建一个Holder类(用于保存持有对象)
            cachedInstances.putIfAbsent(name, new Holder<>());
            holder = cachedInstances.get(name);
        }
        return holder;
    }

3.3 createExtension()

 private T createExtension(String name) {
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            // 从map中获取该接口对应的实例
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                // 设置实例
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            // 注入set方法
            injectExtension(instance);
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (CollectionUtils.isNotEmpty(wrapperClasses)) {
                for (Class<?> wrapperClass : wrapperClasses) {
                // 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例。
                // 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            // LifeCycle组件初始化回调方法
            initExtension(instance);
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
                    type + ") couldn't be instantiated: " + t.getMessage(), t);
        }
    }

 /**
 * 默认加载以下两个Extension类
 * spi -> org.apache.dubbo.common.extension.factory.SpiExtensionFactory
 * spring -> org.apache.dubbo.config.spring.extension.SpringExtensionFactory
 */
 private Map<String, Class<?>> getExtensionClasses() {
        Map<String, Class<?>> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

 /**
 * 去META-INF/dubbo 中加载Extension类
 * 优先加载 /dubbo/internal 中的类
 */
 private Map<String, Class<?>> loadExtensionClasses() {
     	// 获取注解中我们定义的名字
        cacheDefaultExtensionName();

        Map<String, Class<?>> extensionClasses = new HashMap<>();
		// 依次从 dubbo/internal、dubbo/、services 三个路径下加载类
        for (LoadingStrategy strategy : strategies) {
            loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
            loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
        }

        return extensionClasses;
    }

 private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
                               boolean extensionLoaderClassLoaderFirst, String... excludedPackages) {
        String fileName = dir + type;
        try {
            Enumeration<java.net.URL> urls = null;
            ClassLoader classLoader = findClassLoader();
            
            // try to load from ExtensionLoader's ClassLoader first
            if (extensionLoaderClassLoaderFirst) {
                ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
                if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
                    urls = extensionLoaderClassLoader.getResources(fileName);
                }
            }
            // 判断路径下资源是否存在
            if(urls == null || !urls.hasMoreElements()) {
                if (classLoader != null) {
                    urls = classLoader.getResources(fileName);
                } else {
                    urls = ClassLoader.getSystemResources(fileName);
                }
            }

            if (urls != null) {
                while (urls.hasMoreElements()) {
                    // 获取资源地址
                    java.net.URL resourceURL = urls.nextElement();
                    // 以 name -> class 存入map中
                    loadResource(extensionClasses, classLoader, resourceURL, excludedPackages);
                }
            }
        } catch (Throwable t) {
            logger.error("Exception occurred when loading extension class (interface: " +
                    type + ", description file: " + fileName + ").", t);
        }
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!