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() + "]";

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370498.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带有自定义注释的Java注释教程

Java注释提供有关代码的信息&#xff0c;并且它们对所注释的代码没有直接影响。 在本教程中&#xff0c;我们将学习Java注释&#xff0c;如何编写自定义注释 &#xff0c;注释用法以及如何使用反射来解析注释 。 注释是在Java 1.5中引入的&#xff0c;现在它已在Hibernate&…

mybatis通用mapper_全网最全Mapper解析,附实操代码帮你更好理解

今天给大家介绍一位老朋友当你第一次接触Java开发的时候&#xff0c;这个老朋友就和你形影不离&#xff0c;当你要进行ORM的时候&#xff0c;单表的增删改查&#xff0c;这位老朋友给了你极大的帮助&#xff0c;不知道你想到他了吗&#xff1f;对&#xff0c;这就是通用mapper&…

初尝微信小程序2-基本框架

基本框架&#xff1a; .wxml &#xff1a;页面骨架 .wxss &#xff1a;页面样式 .js &#xff1a;页面逻辑 描述一些行为 .json &#xff1a;页面配置 创建一个小程序之后&#xff0c;app.js,app.json,app.wxss是必须的&#xff0c;而且名字也不能随意更改&#xff0c;…

JSP内置对象,动作,指令总结

总的来说关于JSP界面有九大内置对象,7大动作,三大指令,现在博主就将这些粘贴出来,此文是很久前整理的学习笔记,如有雷同请谅解! jsp九大内置对象:1>out 向客户端输出数据,字节流.如out.print(" dgaweyr"); 2>request 接收客户端的http请求.String getParameter…

洛谷 P1795 无穷的序列_NOI导刊2010提高(05)

P1795 无穷的序列_NOI导刊2010提高&#xff08;05&#xff09; 题目描述 有一个无穷序列如下&#xff1a; 110100100010000100000… 请你找出这个无穷序列中指定位置上的数字 输入输出格式 输入格式&#xff1a;第一行一个正整数N&#xff0c;表示询问次数&#xff1b; 接下来的…

java 取字符串中的数字_java截取字符串中的数字

随便给你一个含有数字的字符串&#xff0c;比如&#xff1a;String s"eert343dfg56756dtry66fggg89dfgf";那我们如何把其中的数字提取出来呢&#xff1f;大致有以下几种方法&#xff0c;正则表达式&#xff0c;集合类&#xff0c;还有就是String类提供的方法。1 Stri…

番石榴的对象类:Equals,HashCode和ToString

如果您有幸使用JDK 7 &#xff0c;那么新的可用Objects类 &#xff08; 至少对我来说 &#xff09;是实现“通用” Java对象方法&#xff08;例如equals&#xff08;Object&#xff09; [with Objects.equals&#xff08;Object&#xff0c;Object &#xff09; ]&#xff0c; …

此服务器的时钟与主域控制器的时钟不一致_中移动“超高精度时间同步服务器”开标,两家中标...

8月25日&#xff0c;中国移动发布《2020年至2022年同步网设备集中采购_中标候选人公示》公告。两家中标。同步网技术比较小众&#xff0c;但是同步网是5G承载网的重要一环&#xff0c;分享一下&#xff0c;供大家参考。中标情况 标包1-时钟同步设备中标候选人依次排序为&#x…

java 异常管理员_GitHub - kangZan/JCatch: Exception异常管理平台,支持Java、PHP、Python等多种语言...

什么是JCatch当程序发生异常(Exception)&#xff0c;处理方式一般是通过日志文件记录下来&#xff0c;这种方式很容易被忽略&#xff0c;而且查询起来比较麻烦。JCatch提供了一种方案&#xff0c;当程序发生异常时&#xff0c;通过JCatch平台接口提交到JCatch平台&#xff0c;由…

oled

gnd、vcc、clk、miso、rst、mosi、cs 转载于:https://www.cnblogs.com/scrazy/p/7892733.html

使用html css js实现计算器

使用html css js实现计算器&#xff0c;开启你的计算之旅吧 效果图&#xff1a; 代码如下&#xff0c;复制即可使用&#xff1a; <!DOCTYPE html><html lang"en"> <head> <meta charset"utf-8"> <style> /* 主体 */ .co…

面向对象的三个基本特征

面向对象的三个基本特征是&#xff1a;封装、继承、多态。封装 封装最好理解了。封装是面向对象的特征之一&#xff0c;是对象和类概念的主要特性。封装&#xff0c;也就是把客观事物封装成抽象的类&#xff0c;并且类可以把自己的数据和方法只让可信的类或者对象操作&#xff…

Spring构造函数注入和参数名称

在运行时&#xff0c;除非在启用了调试选项的情况下编译类&#xff0c;否则Java类不会保留构造函数或方法参数的名称。 这对于Spring构造函数注入有一些有趣的含义。 考虑以下简单的类 package dbg; public class Person {private final String first;private final String …

java学习文档_资深程序员带你深入了解JAVA知识点,实战篇,PDF文档

JAVA 集合JAVA 集合面对浩瀚的网络学习资源&#xff0c;您是否为很难找到适合自己的学习资源而感到苦恼过&#xff1f;那么&#xff0c;您来对地方了。在这里我们帮助大家整理了一份适于轻松学习 Java 文章的清单。JVM文字太多&#xff0c;不便之处敬请谅解JAVA 集合文字太多&a…

java程序员电影_Java程序员必看电影:Java 4-ever

(Scene: A father and his son playing "throw-and-catch")(场景: 一位父亲和儿子玩丢接球游戏)Narrator: They appear to be a perfect family旁白: 他们看起来像是一个完美的家庭(Scene: bedtime story)(场景: 床边故事)Father: Export all OLE objects with the c…

深入理解softmax函数

Softmax回归模型&#xff0c;该模型是logistic回归模型在多分类问题上的推广&#xff0c;在多分类问题中&#xff0c;类标签 可以取两个以上的值。Softmax模型可以用来给不同的对象分配概率。即使在之后&#xff0c;我们训练更加精细的模型时&#xff0c;最后一步也需要用soft…

《第二章:深入了解超文本》

从本章开始要去除无用的话&#xff0c;只在笔记中记载要点----- 使用<a>元素创建一个超文本链接&#xff0c;链接到另一个Web页面。 <a>元素的内容会成为Web页面中可单击的文本。 href属性告诉浏览器链接的目标文件。 了解属性 例&#xff1a;style的type属性指定…

strcpy函数_错误更正(拷贝赋值函数的正确使用姿势)

这是一篇对什么是C的The Rule of Three的错误更正和详细说明。阅读时间7分钟。难度⭐⭐⭐虽然上一篇文章的阅读量只有凄惨的两位数&#xff0c;但是怀着对小伙伴负责的目的&#xff0c;必须保证代码的正确性。这是大厨做技术自媒体的态度。前文最后一段代码是这样的&#xff1a…

将Java应用程序打包为一个(或胖)JAR

这篇文章的目标是一个有趣但非常强大的概念&#xff1a;将应用程序打包为单个可运行的JAR文件&#xff0c;也称为一个或胖 JAR文件。 我们习惯了大型WAR归档文件&#xff0c;其中包含所有打包在某些公用文件夹结构下的依赖项。 使用类似于JAR的打包&#xff0c;情况有所不同&a…

学习java的第三天,猜字符的小程序

关于猜字符的小程序 主要实现&#xff1a;随机输出5个字母&#xff0c;用户输入猜测的字母&#xff0c;进行对比得出结果 主要有3个方法&#xff1a;主方法main(); 产生随机字符的方法generate(); 比较用户输入的字符与随机产生的字符的方法check&#xff08;&#xff09;&…