日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java SPI的簡單小實例

瀏覽:43日期:2022-08-29 13:27:02

JDK有個ServiceLoader類,在java.util包里,支持按約定目錄/META-INF/services去找到接口全路徑命名的文件,讀取文件內容得到接口實現類的全路徑,加載并實例化。如果我們在自己的代碼中定義一個接口,別人按接口實現并打包好了,那么我們只需要引入jar包,通過ServiceLoader就能夠把別人的實現用起來。舉個例子,JDK中的JDBC提供一個數據庫連接驅動接口,不同的廠商可以有不同的實現,如果它們給的jar包里按規定提供了配置和實現類,那么我們就可以執行不同的數據庫連接操作,比如MySql的jar包里就會有自己的配置:

Java SPI的簡單小實例

這里文件名就是接口:

Java SPI的簡單小實例

文件內容是實現類:

Java SPI的簡單小實例

我們自己實現一個簡單例子,不需要打jar包,把目錄放到spring boot的resources下即可,這里就是classpath,跟你放jar包里效果一樣。

1、定義一個接口:

package com.wlf.service;public interface ITest { void saySomething();}

2、定義兩個實現:

package com.wlf.service.impl;import com.wlf.service.ITest;public class ITestImpl1 implements ITest { @Override public void saySomething() { System.out.println('Hi, mia.'); }}

package com.wlf.service.impl;import com.wlf.service.ITest;public class ITestImpl2 implements ITest { @Override public void saySomething() { System.out.println('Hello, world.'); }}

3、按預定新增/META-INF/services/com.wlf.service.ITest文件:

com.wlf.service.impl.ITestImpl1com.wlf.service.impl.ITestImpl2

Java SPI的簡單小實例

4、定義一個執行類,通過ServiceLoader加載并實例化,調用實現類方法,跑一下:

package com.wlf.service;import java.util.Iterator;import java.util.ServiceLoader;public class TestServiceLoader { public static void main(String[] args) { ServiceLoader<ITest> serviceLoader = ServiceLoader.load(ITest.class); Iterator<ITest> iTests = serviceLoader.iterator(); while (iTests.hasNext()) { ITest iTest = iTests.next(); System.out.printf('loading %sn', iTest.getClass().getName()); iTest.saySomething(); } }}

打印結果:

Java SPI的簡單小實例

ServiceLoader源碼比較簡單,可以看下上面我們使用到的標黃了的方法:

/** * Lazily loads the available providers of this loader’s service. * * <p> The iterator returned by this method first yields all of the * elements of the provider cache, in instantiation order. It then lazily * loads and instantiates any remaining providers, adding each one to the * cache in turn. * * <p> To achieve laziness the actual work of parsing the available * provider-configuration files and instantiating providers must be done by * the iterator itself. Its {@link java.util.Iterator#hasNext hasNext} and * {@link java.util.Iterator#next next} methods can therefore throw a * {@link ServiceConfigurationError} if a provider-configuration file * violates the specified format, or if it names a provider class that * cannot be found and instantiated, or if the result of instantiating the * class is not assignable to the service type, or if any other kind of * exception or error is thrown as the next provider is located and * instantiated. To write robust code it is only necessary to catch {@link * ServiceConfigurationError} when using a service iterator. * * <p> If such an error is thrown then subsequent invocations of the * iterator will make a best effort to locate and instantiate the next * available provider, but in general such recovery cannot be guaranteed. * * <blockquote style='font-size: smaller; line-height: 1.2'><span * style='padding-right: 1em; font-weight: bold'>Design Note</span> * Throwing an error in these cases may seem extreme. The rationale for * this behavior is that a malformed provider-configuration file, like a * malformed class file, indicates a serious problem with the way the Java * virtual machine is configured or is being used. As such it is * preferable to throw an error rather than try to recover or, even worse, * fail silently.</blockquote> * * <p> The iterator returned by this method does not support removal. * Invoking its {@link java.util.Iterator#remove() remove} method will * cause an {@link UnsupportedOperationException} to be thrown. * * @implNote When adding providers to the cache, the {@link #iterator * Iterator} processes resources in the order that the {@link * java.lang.ClassLoader#getResources(java.lang.String) * ClassLoader.getResources(String)} method finds the service configuration * files. * * @return An iterator that lazily loads providers for this loader’s * service */ public Iterator<S> iterator() { return new Iterator<S>() { 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();return lookupIterator.next(); } public void remove() {throw new UnsupportedOperationException(); } }; }

我們用到的迭代器其實是一個Map:

// Cached providers, in instantiation order private LinkedHashMap<String,S> providers = new LinkedHashMap<>();

它用來緩存加載的實現類,真正執行的是lookupIterator:

// The current lazy-lookup iterator private LazyIterator lookupIterator;

我們看下它的hasNext和next方法:

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); } } 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 boolean hasNextService() { if (nextName != null) {return true; } if (configs == null) {try { String fullName = PREFIX + service.getName(); if (loader == null) 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;}pending = parse(service, configs.nextElement()); } nextName = pending.next(); return true; } private S nextService() { if (!hasNextService())throw new NoSuchElementException(); 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);return p; } catch (Throwable x) {fail(service, 'Provider ' + cn + ' could not be instantiated', x); } throw new Error(); // This cannot happen } 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); } }

hasNext查找實現類,并指定了類路徑:

private static final String PREFIX = 'META-INF/services/';

具體查找操作看這里:

pending = parse(service, configs.nextElement());

next則是實例化加載到的實現類,使用反射Class.forName加載類、newInstance實例化對象。

以上就是Java SPI的簡單小實例的詳細內容,更多關于Java SPI實例的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲五月婷婷| 99pao成人国产永久免费视频| 久久久男人天堂| 欧美亚洲福利| 亚洲精品动态| 亚洲天堂av资源在线观看| 91精品蜜臀一区二区三区在线| 国产精品观看| 奇米777国产一区国产二区| 91免费精品国偷自产在线在线| 国产亚洲一级| 免费av一区二区三区四区| 国产精品久久久久久久久久齐齐 | 日韩视频一区二区三区在线播放免费观看| 麻豆久久一区二区| 国产亚洲电影| 欧美亚洲二区| 青青国产精品| 91成人小视频| 国产亚洲一区二区三区啪| 亚洲日韩视频| 少妇精品在线| 日本va欧美va欧美va精品| 香蕉久久久久久| 亚洲理论在线| 91久久视频| 婷婷亚洲综合| 不卡在线一区二区| 精品91久久久久| 久久国产影院| 国产一区国产二区国产三区 | 亚洲在线一区| 日韩中文字幕麻豆| 蜜桃视频第一区免费观看| 亚洲一区二区免费在线观看| 在线精品视频一区| 日日摸夜夜添夜夜添国产精品| 亚洲毛片在线免费| 国产日韩欧美| 成人影视亚洲图片在线| 亚洲福利一区| 丝袜亚洲另类欧美| 亚洲精品四区| 日本综合精品一区| 久久午夜影院| 成人看片网站| 香蕉国产精品| 亚洲一区av| 国产精品一区二区三区美女 | 亚洲精品字幕| 国产精品一区免费在线| 91一区二区| 中文在线一区| 日韩精品久久久久久| 久久久精品国产**网站| 日韩1区在线| 亚洲激情欧美| 免费久久99精品国产| 欧美精品国产| 91看片一区| 亚洲精品福利| av资源中文在线| 午夜在线视频一区二区区别| 青青国产91久久久久久| 美女福利一区二区三区| 久久99伊人| 欧美激情视频一区二区三区免费| 日本综合字幕| 蜜臀av亚洲一区中文字幕| 国产高清视频一区二区| 久久免费大视频| 日韩综合小视频| 欧美激情精品| 国产精品腿扒开做爽爽爽挤奶网站| 欧美日韩一区二区三区四区在线观看 | 欧美日韩一二| 亚洲欧洲一区二区天堂久久| 国产精品最新自拍| 91精品婷婷色在线观看| 日韩欧美中文字幕一区二区三区| 黄色在线网站噜噜噜| 中文亚洲免费| 国产不卡精品在线| 男人的天堂久久精品| 精品国产乱码| 欧美va亚洲va日韩∨a综合色| 欧美三级第一页| 91精品99| 精品免费视频| 亚洲欧美网站在线观看| 精品欧美一区二区三区在线观看| 日欧美一区二区| 99久精品视频在线观看视频| 国产乱码精品| 视频一区二区三区入口| 国产精品麻豆久久| 日韩精品三级| 日韩不卡在线| 日本亚洲欧美天堂免费| 欧美亚洲激情| 日韩 欧美一区二区三区| 激情综合网址| 久久精品免视看国产成人| 亚洲精品麻豆| 婷婷综合网站| 岛国av在线播放| 久久激五月天综合精品| 日韩精品一级二级 | 欧美国产先锋| 在线日韩成人| 亚洲特色特黄| 不卡福利视频| 日韩欧美激情电影| 日韩福利在线观看| 蜜芽一区二区三区| 亚洲欧美日本日韩| 999精品一区| 今天的高清视频免费播放成人| 高清久久一区| 欧美天堂一区| 日韩精品一区二区三区中文字幕| 国产字幕视频一区二区| 激情婷婷欧美| 成人久久一区| 亚洲国产一区二区在线观看 | 亚洲午夜国产成人| 夜夜嗨一区二区三区| 久久精选视频| 国产精品久久久久av电视剧| 久久精品国产免费| 国产精品白丝一区二区三区| 欧美日韩黄网站| 日韩va欧美va亚洲va久久| 日韩专区在线视频| 9色精品在线| 亚洲精品极品少妇16p| 国产色播av在线| 最新国产精品| 日韩高清不卡一区二区| 日韩一区免费| 天堂精品久久久久| 婷婷亚洲成人| 免费在线看一区| 亚洲另类av| 日韩国产91| 欧美日韩亚洲一区三区| 日韩国产一区二| 日韩精品视频在线看| 日韩 欧美一区二区三区| 香蕉久久一区| 日韩高清欧美激情| 国产日韩视频| 91欧美日韩在线| 国产精品久av福利在线观看| 国产日韩欧美三级| 国产精品v亚洲精品v日韩精品| 国产欧美久久一区二区三区| 国产精品久久久久久久久免费高清 | 中文不卡在线| 自拍自偷一区二区三区| 亚欧洲精品视频在线观看| 婷婷视频一区二区三区| 91成人在线网站| 91精品啪在线观看国产爱臀| 国产精品一区二区精品视频观看| 日韩免费精品| 国产精品玖玖玖在线资源| 麻豆免费精品视频| 精品视频国产| 精品亚洲美女网站| 亚洲激情欧美| 天海翼精品一区二区三区| 婷婷亚洲精品| 日韩一区二区三区精品| 美女国产一区二区三区| 久久av免费| 999久久久免费精品国产| 亚洲欧美久久久| 中文字幕一区二区av| 久久狠狠久久| 国产精品一区二区av交换| 国产精品色婷婷在线观看| 国产精品多人| 中文在线а√在线8| 99riav1国产精品视频| 久久av一区二区三区| 亚欧成人精品| 99精品在线观看| 中文国产一区| 国产精品最新| 99成人在线视频| 亚洲久久在线| 成人在线视频区| 黄色日韩在线| 国产日产高清欧美一区二区三区| 日韩欧美不卡| 日本成人在线网站| 91看片一区| 日本视频中文字幕一区二区三区| 福利一区和二区|