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.pswp.cn/news/370498.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/370498.shtml
英文地址,請注明出處:http://en.pswp.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;&…