JavaSPI详解( 二 )

运行结果
class cn.bmilk.chat.spi.EurekaRegistrycn.bmilk.chat.spi.EurekaRegistry@12a3a380registry , host = 127.0.0.1  port = 10086class cn.bmilk.chat.spi.ZookeeperRegistrycn.bmilk.chat.spi.ZookeeperRegistry@29453f44registry , host = 127.0.0.1  port = 10086从运行结果中可以看到EurekaRegistryZookeeperRegistry都被实例化并且生成相应的对象 。但是我们全程并没有显示的加载和生成EurekaRegistryZookeeperRegistry类对象,那么是怎么来的呢?
SPI机制的实现SPI机制的核心就是ServiceLoader类 。其主要的属性如下:
    // 指出接口配置文件的位置,也就是为什么要在META-INF/services/下创建接口的全限定名文件的原因    private static final String PREFIX = "META-INF/services/";    // 正在被加载的类(接口)的class对象    private final Class<S> service;    // 加载使用的类加载器    private final ClassLoader loader;    // 创建 ServiceLoader 时采用的访问控制上下文    private final AccessControlContext acc;    // 缓存已经加载的实现, 按实例化顺序缓存    private LinkedHashMap<String,S> providers = new LinkedHashMap<>();    // The current lazy-lookup iterator    private LazyIterator lookupIterator;load()方法的实现如下:
    public static <S> ServiceLoader<S> load(Class<S> service) {        ClassLoader cl = Thread.currentThread().getContextClassLoader();        // 使用当前线程的ClassLoader进行加载待加载的实现类        return ServiceLoader.load(service, cl);    }    public static <S> ServiceLoader<S> load(Class<S> service,                                            ClassLoader loader)    {        // load 方法本质是创建一个ServiceLoader对象        return new ServiceLoader<>(service, loader);    }    // new ServiceLoader<>(service, loader)的实现    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();    }    public void reload() {        providers.clear();        // 根据接口类型(父类)和类加载器初始化LazyIterator        lookupIterator = new LazyIterator(service, loader);    }    private LazyIterator(Class<S> service, ClassLoader loader) {            this.service = service;            this.loader = loader;        }

经验总结扩展阅读