ServiceLoader源码解析

ServiceLoader源码解析

示例代码

public class MyTest01 {

    public static void main(String[] args) {
        ServiceLoader<Driver> loader = ServiceLoader.load(Driver.class);
        Iterator<Driver> iterator = loader.iterator();
        while (iterator.hasNext()){
            Driver dirver = iterator.next();
            System.out.println(dirver.getClass());
        }
    }
}

首先我们看一下示例代码的步骤

1. 执行ServiceLoader.load()方法

ServiceLoader.load()
public static <S> ServiceLoader<S> load(Class<S> service) {
    // 获取当前线程的上下文类加载器
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    return ServiceLoader.load(service, cl);
}
初始化ServiceLoader (private内部构造器)
private ServiceLoader(Class<S> svc, ClassLoader cl) {
    service = Objects.requireNonNull(svc, "Service interface cannot be null");
    // 如果线程上下文加载器为空, 则使用ClassLoader.getSystemClassLoader()即AppClassLoader
    loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
    acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null;
    // 重新加载
    reload();
}

2. 获取迭代器

loader.iterator()
public Iterator<S> iterator() {
   
    return new Iterator<S>() {
		// 实际上是包装了 provider.entrySet() 的迭代器
         // provider是对提供者列表的集合
        Iterator<Map.Entry<String,S>> 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();
            // 迭代器的next()方法调用了lookupIterator的next()方法
            return lookupIterator.next();
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }

    };
}
LazyIterator

上面获取迭代器的源码中提到了lookupIterator, lookupIterator是LazyIterator的实例

// 实现Iterator迭代器接口
private class LazyIterator
        implements Iterator<S>
    {
        ...
        private LazyIterator(Class<S> service, ClassLoader loader) {
        	// 设置要加载的类型
            this.service = service;
            // 设置类加载器, 也就是线程上下文加载器
            this.loader = loader;
        }

	    // LazyIterator迭代器的next()方法调用了nextService()方法
	    // nextService()方法实现了通过Class.forName()加载类, 当然这里面指定了类加载器
        private S nextService() {
            ...
            try {
                c = Class.forName(cn, false, loader);
            } catch (ClassNotFoundException x) {
                fail(service,
                     "Provider " + cn + " not found");
            }
           ...
        }
        ...

    }

看到这里, 相必大家已经清楚了ServiceLoader.load()方法的过程, 简单总结一下:

  • 设置要加载的类和类加载器(使用的是线程上下文的类加载器)
  • 通过迭代器可以遍历获取到的服务提供者(即已经加载的类的实例), 实际上是对LazyIterator的包装
  • 最终, LazyIterator是通过Class.forName来通过指定的类加载器加载类

那么, 最后还有一个问题, LazyIterator是在哪里初始化的?

reload()
public void reload() {
    // 清空provider, providers按照实例化顺序缓存服务提供者
    providers.clear();
    // 实例化LazyIterator, LazyIterator是一个静态内部类用来实现 fully-lazy provider lookup
    lookupIterator = new LazyIterator(service, loader);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值