跳转至

时间: 2018/9/14 15:32:32

参考:

  1. java.util.ServiceLoader

ServiceLoader

简介

服务加载工具类,从 META-INF/services/ 目录查找接口的实现信息,然后初始化接口的实现类,拿到具体的实例化之后的对象,之后使用接口定义的服务。

源码解析

内部字段

# 服务提供类配置文件     
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<>();
# 懒加载实现需要服务的时候再加载
private LazyIterator lookupIterator;

加载过程:

  1. 调用加载方法,创建 ServiceLoader 对象

    ```java ServiceLoader drivers = ServiceLoader.load(Driver.class)
    public static ServiceLoader load(Class service) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return ServiceLoader.load(service, cl); }

    public static ServiceLoader load(Class service, ClassLoader loader){ return new ServiceLoader<>(service, loader); }S ```

  2. ServiceLoader 创建过程

    ```java private ServiceLoader(Class svc, ClassLoader cl) { # 验证Service 接口、类加载器判断或初始化、访问控制器判断或初始化 service = Objects.requireNonNull(svc, "Service interface cannot be null"); loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl; acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null; //重接加载接口定义 reload(); }

    //重新加载接口提供者信息 public void reload() { providers.clear(); # 初始化懒加载器 lookupIterator = new LazyIterator(service, loader); } ```

  3. 获取接口提供者

    ```java

    初始化ServiceLoader

    ServiceLoader drivers = ServiceLoader.load(Driver.class);

    获取迭代器, ServiceLoader 实现 Iterable 接口

    Iterator driverIterator = drivers.iterator(); while (driverIterator.hasNext()) { System.out.println(driverIterator.next().getClass().getName()); }

    drivers.iterator()(ServiceLoader.iterator() 方法实现)

    public Iterator iterator() { return new Iterator() { // 使用外部类的 providers 初始化 knownProviders Iterator> knownProviders = providers.entrySet().iterator();

        public boolean hasNext() {
            if (knownProviders.hasNext()){
                return true;
            }   
            return lookupIterator.hasNext();
        }
    
        public S next() {
            if (knownProviders.hasNext()){
                return knownProviders.next().getValue();
            }
            return lookupIterator.next();
        }
    
        public void remove() {
            throw new UnsupportedOperationException();
        }
    
    };
    

    } ```

  4. lookupIterator (LazyIterator) 实现解析:

    ```java

    字段

    Class service; //服务接口 ClassLoader loader; //类加载器 Enumeration configs = null; //所有提供者配置信息 Iterator pending = null; //服务提供者迭代器 String nextName = null; //下一个服务提供者的名字

    判断有没有服务提供者

    public boolean hasNext() { if (acc == null) { return hasNextService(); } else { PrivilegedAction action = new PrivilegedAction() { public Boolean run() { return hasNextService(); } }; return AccessController.doPrivileged(action, acc); } }

    判断有没有服务

    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()); } //设置下一个服务提供者的类名,next方法使用名字加载和初始化对应的实现类 nextName = pending.next(); return true; }

    获取下一个服务提供者

    public S next() { if (acc == null) { return nextService(); } else { PrivilegedAction action = new PrivilegedAction() { public S run() { return nextService(); } }; return AccessController.doPrivileged(action, acc); } }

    获取下一个服务提供者类

    private S nextService() { if (!hasNextService()) throw new NoSuchElementException(); String cn = nextName; nextName = null; Class<?> c = null; try { # 加载类信息 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 } ```