JDK-SPI源码分析

JDK-SPI实现原理

标签(空格分隔): SPI


[TOC]

Dubbo扩展点加载是从JDK标准的SPI扩展点发现机制加强而来。看一下JDK-SPI。

DEMO

1.标准接口

 public interface Log {
     void execute();
 }

2.具体实现1

 public class Log4j implements Log {

    public void execute() {
        System.out.println("log4j execute");
    }
}

3.具体实现2

public class Logback implements Log {

    @Override
    public void execute() {
        System.out.println("logback execute..");
    }
}

4.指定实现:META-INF/services/Log

Log4j

5.Main

public class Main {
    public static void main(String[] args) {
        ServiceLoader<Log> serviceLoader = ServiceLoader.load(Log.class);
        Iterator<Log> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            Log log = iterator.next();
            log.execute();
        }
    }
}

源码解析

1.Main获取ServiceLoader

ServiceLoader<Log> serviceLoader = ServiceLoader.load(Log.class);

ServiceLoader属性:

//定义实现类的接口文件目录
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;

ServiceLoader初始化:

public static <S> ServiceLoader<S> load(Class<S> service) {
    // 获取classLoader
    ClassLoader cl = Thread.currentThread().getContextClassLoader();
    return ServiceLoader.load(service, cl);
}

public static <S> ServiceLoader<S> load(Class<S> service,ClassLoader loader){
    return 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();// 清理缓存
    lookupIterator = new LazyIterator(service, loader);// 创建迭代器
}

迭代器:

Iterator<Log> iterator = serviceLoader.iterator();
while (iterator.hasNext()) {
    Log log = iterator.next();
    log.execute();
}

实现:

public Iterator<S> iterator() {
    return new Iterator<S>() {
            // 遍历LinkedList
            Iterator<Map.Entry<String,S>> knownProviders = providers.entrySet().iterator();
            // 先从provider(缓存)中获取,如果有,返回true,如果没有,从LazyIterator中查找
            public boolean hasNext() {
                if (knownProviders.hasNext())
                    return true;
                return lookupIterator.hasNext();
            }
            // 从缓存中获取,有,返回对象实例;如果没有,从LazyIterator来进行获取
            public S next() {
                if (knownProviders.hasNext())
                    return knownProviders.next().getValue();
                return lookupIterator.next();
            }
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

LazyIterator属性:

Class<S> service;// 接口
ClassLoader loader;// 定位,加载,实例化类
Enumeration<URL> configs = null;// 配置文件地址
Iterator<String> pending = null;// 配置文件内容,存储实现类名称,ArrayList
String nextName = null;// 当前实现类名称

hasNext():

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);
    }
}

private boolean hasNextService() {
    if (nextName != null) {
        return true;
    }
    if (configs == null) {
        try {
            // META-INF/services/Log
            String fullName = PREFIX + service.getName();
            if (loader == null)
                // 从META-INF/services/Log获取配置文件
                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;
        }
        // 解析配置文件 放在ArrayList
        pending = parse(service, configs.nextElement());
    }
    // 指定NextName
    nextName = pending.next();
    return true;
}

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() {
    if (!hasNextService())
        throw new NoSuchElementException();
    String cn = nextName;
    nextName = null;
    Class<?> c = null;
    try {
        // 加载nextName代表的类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());
        // 存储在provider(缓存)中,供后续查找
        providers.put(cn, p);
        return p;
    } catch (Throwable x) {
        fail(service,
             "Provider " + cn + " could not be instantiated",
             x);
    }
    throw new Error();          // This cannot happen
}

log.execute()执行结果:log4j execute

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值