java provider_Java SPI(Service Provider Interface)

//ServiceLoader实现了Iterable接口,可以遍历所有的服务实现者

public final class ServiceLoader

implements Iterable{//查找配置文件的目录

private static final String PREFIX = "META-INF/services/";//表示要被加载的服务的类或接口

private final Classservice;//这个ClassLoader用来定位,加载,实例化服务提供者

private finalClassLoader loader;//访问控制上下文

private finalAccessControlContext acc;//缓存已经被实例化的服务提供者,按照实例化的顺序存储

private LinkedHashMap providers = new LinkedHashMap<>();//The current lazy-lookup iterator

privateLazyIterator lookupIterator;//重新加载,就相当于重新创建ServiceLoader了,用于新的服务提供者安装到正在运行的Java虚拟机中的情况

public voidreload() {//清空缓存中所有已实例化的服务提供者

providers.clear();//新建一个迭代器,该迭代器会从头查找和实例化服务提供者

lookupIterator = newLazyIterator(service, loader);

}//私有构造器//使用指定的类加载器和服务创建服务加载器//如果没有指定类加载器,使用系统类加载器,就是应用类加载器。

private ServiceLoader(Classsvc, 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 static void fail(Class>service, String msg, Throwable cause)throwsServiceConfigurationError

{throw new ServiceConfigurationError(service.getName() + ": " +msg,

cause);

}private static void fail(Class>service, String msg)throwsServiceConfigurationError

{throw new ServiceConfigurationError(service.getName() + ": " +msg);

}private static void fail(Class> service, URL u, intline, String msg)throwsServiceConfigurationError

{

fail(service, u+ ":" + line + ": " +msg);

}//解析服务提供者配置文件中的一行//首先去掉注释校验,然后保存//返回下一行行号//重复的配置项和已经被实例化的配置项不会被保存

private int parseLine(Class> service, URL u, BufferedReader r, intlc,

Listnames)throwsIOException, ServiceConfigurationError

{//读取一行

String ln =r.readLine();if (ln == null) {return -1;

}//#号代表注释行

int ci = ln.indexOf('#');if (ci >= 0) ln = ln.substring(0, ci);

ln=ln.trim();int n =ln.length();if (n != 0) {if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))

fail(service, u, lc,"Illegal configuration-file syntax");int cp = ln.codePointAt(0);if (!Character.isJavaIdentifierStart(cp))

fail(service, u, lc,"Illegal provider-class name: " +ln);for (int i = Character.charCount(cp); i < n; i +=Character.charCount(cp)) {

cp=ln.codePointAt(i);if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))

fail(service, u, lc,"Illegal provider-class name: " +ln);

}if (!providers.containsKey(ln) && !names.contains(ln))

names.add(ln);

}return lc + 1;

}//解析配置文件,解析指定的url配置文件//使用parseLine方法进行解析,未被实例化的服务提供者会被保存到缓存中去

private Iterator parse(Class>service, URL u)throwsServiceConfigurationError

{

InputStream in= null;

BufferedReader r= null;

ArrayList names = new ArrayList<>();try{

in=u.openStream();

r= new BufferedReader(new InputStreamReader(in, "utf-8"));int lc = 1;while ((lc = parseLine(service, u, r, lc, names)) >= 0);

}catch(IOException x) {

fail(service,"Error reading configuration file", x);

}finally{try{if (r != null) r.close();if (in != null) in.close();

}catch(IOException y) {

fail(service,"Error closing configuration file", y);

}

}returnnames.iterator();

}//Private inner class implementing fully-lazy provider lookup//服务提供者查找的迭代器

private classLazyIteratorimplements Iterator{//服务提供者接口

Classservice;//类加载器

ClassLoader loader;//保存实现类的url

Enumeration configs = null;//保存实现类的全名

Iterator pending = null;//迭代器中下一个实现类的全名

String nextName = null;private LazyIterator(Classservice, ClassLoader loader) {this.service =service;this.loader =loader;

}private booleanhasNextService() {if (nextName != null) {return true;

}if (configs == null) {try{

String fullName= PREFIX +service.getName();if (loader == null)

configs=ClassLoader.getSystemResources(fullName);elseconfigs=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;

}privateS nextService() {if (!hasNextService())throw newNoSuchElementException();

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

}catch(Throwable x) {

fail(service,"Provider " + cn + " could not be instantiated",

x);

}throw new Error(); //This cannot happen

}public booleanhasNext() {if (acc == null) {returnhasNextService();

}else{

PrivilegedAction action = new PrivilegedAction() {public Boolean run() { returnhasNextService(); }

};returnAccessController.doPrivileged(action, acc);

}

}publicS next() {if (acc == null) {returnnextService();

}else{

PrivilegedAction action = new PrivilegedAction() {public S run() { returnnextService(); }

};returnAccessController.doPrivileged(action, acc);

}

}public voidremove() {throw newUnsupportedOperationException();

}

}//获取迭代器//返回遍历服务提供者的迭代器//以懒加载的方式加载可用的服务提供者//懒加载的实现是:解析配置文件和实例化服务提供者的工作由迭代器本身完成

public Iteratoriterator() {return new Iterator() {//按照实例化顺序返回已经缓存的服务提供者实例

Iterator>knownProviders=providers.entrySet().iterator();public booleanhasNext() {if(knownProviders.hasNext())return true;returnlookupIterator.hasNext();

}publicS next() {if(knownProviders.hasNext())returnknownProviders.next().getValue();returnlookupIterator.next();

}public voidremove() {throw newUnsupportedOperationException();

}

};

}//为指定的服务使用指定的类加载器来创建一个ServiceLoader

public static ServiceLoader load(Classservice,

ClassLoader loader)

{return new ServiceLoader<>(service, loader);

}//使用线程上下文的类加载器来创建ServiceLoader

public static ServiceLoader load(Classservice) {

ClassLoader cl=Thread.currentThread().getContextClassLoader();returnServiceLoader.load(service, cl);

}//使用扩展类加载器为指定的服务创建ServiceLoader//只能找到并加载已经安装到当前Java虚拟机中的服务提供者,应用程序类路径中的服务提供者将被忽略

public static ServiceLoader loadInstalled(Classservice) {

ClassLoader cl=ClassLoader.getSystemClassLoader();

ClassLoader prev= null;while (cl != null) {

prev=cl;

cl=cl.getParent();

}returnServiceLoader.load(service, prev);

}/*** Returns a string describing this service.

*

*@returnA descriptive string*/

publicString toString() {return "java.util.ServiceLoader[" + service.getName() + "]";

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值