SPI

作者: Audience0 | 来源:发表于2019-08-17 16:49 被阅读0次

    SPI,全程为Service Provider Interface,是一种服务发现机制.它通过在ClassPath下META-INF/services文件夹查找文件,自动加载文件中所定义的类.

    在这个过程中,可以通过ServiceLoader.load以及ServiceLoader.iterator来获取文件中定义的实现类
    其中,文件名为接口的全限定名,文件中的定义的类是该接口的实现类的全限定名


    ServiceLoader部分源码如下:
    ServiceLoader.load() 主要是初始化对象

    
    public final class ServiceLoader<S>
            implements Iterable<S>
    {
        //定义查询文件的目录
        private static final String PREFIX = "META-INF/services/";
    
        //要加载的接口
        private final Class<S> service;
        //类加载器
        private final ClassLoader loader;
    
        private final AccessControlContext acc;
        //缓存已加载的实现类
        private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
        //ServiceLoader 的内部类,由它实现加载
        private LazyIterator lookupIterator;
    
        public static <S> ServiceLoader<S> load(Class<S> service,
                                                ClassLoader loader)
        {   //初始化ServiceLoader
            return new ServiceLoader<>(service, loader);
        }
    
        //load 方法,主要做ServiceLoad 及其内部类 LazyIterator 初始化(service,loader),
        public static <S> ServiceLoader<S> load(Class<S> service) {
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            return ServiceLoader.load(service, cl);
        }
    
        public void reload() {
            providers.clear();
            //初始化内部类LazyIterator
            lookupIterator = new LazyIterator(service, loader);
        }
        //校验service是否为空,初始化ServiceLoader
        private ServiceLoader(Class<S> svc, ClassLoader cl) {
            service = Objects.requireNonNull(svc, "Service interface cannot be null");
            loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
            acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
            reload();
        }
        
            private class LazyIterator
                implements Iterator<S>
        {
    
            Class<S> service;
            ClassLoader loader;
            Enumeration<URL> configs = null;
            Iterator<String> pending = null;
            String nextName = null;
            //初始化LazyIterator
            private LazyIterator(Class<S> service, ClassLoader loader) {
                this.service = service;
                this.loader = loader;
            }
      }
    }
    

    ServiceLoader.iterator();获取迭代器,但其实都是在调用其内部类LazyIterator的迭代器

    public final class ServiceLoader<S>  implements Iterable<S>{
          public Iterator<S> iterator() {
            return new Iterator<S>() {
                Iterator<Map.Entry<String,S>> knownProviders
                        = providers.entrySet().iterator();
               
                public boolean hasNext() {
                    if (knownProviders.hasNext())
                        return true;
                   //实际是ServiceLoader内部类LazyIterator的hasNext
                    return lookupIterator.hasNext();
                }
                
                public S next() {
                    if (knownProviders.hasNext())
                        return knownProviders.next().getValue();
                  //实际是ServiceLoader内部类LazyIterator的next
                    return lookupIterator.next();
                }
    
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    }
    

    LazyIterator的实现

    private class LazyIterator implements Iterator<S> {
          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;
            }
    
            private S nextService() {
                 //调用hasNextService判断是否还有元素
                if (!hasNextService())
                    throw new NoSuchElementException();
                String cn = nextName;
                nextName = null;
                Class<?> c = null;
                try {
                   //根据实现类权限定名获取Class
                    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
            }
    
            public boolean hasNext() {
                if (acc == null) {
                    return hasNextService();
                } else {
                    PrivilegedAction<Boolean> action = new PrivilegedAction<Boolean>() {
                        public Boolean run() { return hasNextService(); }
                    };
                    return AccessController.doPrivileged(action, acc);
                }
            }
    
            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);
                }
            }
    
            public void remove() {
                throw new UnsupportedOperationException();
            }
    }
    

    开源框架中的实际应用:


    image.png

    其中foreach相当于调用iterator,以及hasNext,next

    相关文章

      网友评论

          本文标题:SPI

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