最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析

 更新時(shí)間:2022年09月20日 09:33:12   作者:nicky_chin  
這篇文章主要為大家介紹了java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

1 定義

SPI 的全名為 Service Provider Interface ,用于接口尋找服務(wù)實(shí)現(xiàn)類

實(shí)現(xiàn)方式 >標(biāo)準(zhǔn)制定者制定接口 不同廠商編寫針對(duì)于該接口的實(shí)現(xiàn)類,并在jar的“classpath:META-INF/services/全接口名稱”文件中指定相應(yīng)的實(shí)現(xiàn)類全類名 開發(fā)者直接引入相應(yīng)的jar,就可以實(shí)現(xiàn)為接口自動(dòng)尋找實(shí)現(xiàn)類的功能

2 案例實(shí)現(xiàn)

比如我們經(jīng)??吹降木彺骖怌ache,現(xiàn)在有非常多的緩存框架都會(huì)去實(shí)現(xiàn)這個(gè)接口

標(biāo)準(zhǔn)接口

public interface Cache {
    String getName();
    <T> T get(Object key, Class<T> type);
    void put(Object key, Object value);
    void evict(Object key);
    void clear();
}

廠商的具體接口實(shí)現(xiàn)

public class ConcurrentMapCache implements Cache {
    private final String name;
    private final ConcurrentMap<Object, Object> store;
    public ConcurrentMapCache() {
        this("defaultMapCache");
    }
    public ConcurrentMapCache(String name) {
        this(name, new ConcurrentHashMap<>(256), true);
    }
    public ConcurrentMapCache(String name, ConcurrentMap<Object, Object> store, boolean allowNullValues) {
        this.name = name;
        this.store = store;
    }
    @Override
    public final String getName() {
        return this.name;
    }
    @Override
    public <T> T get(Object key, Class<T> type) {
        Object value = this.store.get(key);
        if (value != null && type != null && !type.isInstance(value)) {
            throw new IllegalStateException("Cached value is not of required type [" + type.getName() + "]: " + value);
        }
        return (T) value;
    }
    @Override
    public void put(Object key, Object value) {
        this.store.putIfAbsent(key, value);
    }
    @Override
    public void evict(Object key) {
        this.store.remove(key);
    }
    @Override
    public void clear() {
        this.store.clear();
    }
}

注意:一定要有默認(rèn)無參構(gòu)造器,否則之后無法通過SPI機(jī)制實(shí)例化對(duì)象

配置地址

在resouce下的META-INF\services文件下的spi.Cache文件內(nèi)容是服務(wù)類的全限命名:spi.ConcurrentMapCache

打包jar并引入到項(xiàng)目

測(cè)試

public class CacheSpiTest {
    public static void main(String[] args) {
        ServiceLoader<Cache> serviceLoader = ServiceLoader.load(Cache.class);
        Iterator<Cache> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            Cache cache = iterator.next();
            System.out.println(cache.getName());
            cache.put("user", "nana");
            System.out.println(cache.get("user", String.class));
        }
    }
}

打印結(jié)果:

defaultMapCache
nana

說明獲取到了定制接口的實(shí)現(xiàn)類對(duì)象

通過上述例子,我們知道ServiceLoader是用于通過接口獲取接口實(shí)現(xiàn)類的工具

3 SPI機(jī)制源碼分析

3.1 load加載過程

ServiceLoader成員變量

//SPI約定獲取擴(kuò)展接口路徑的文件
private static final String PREFIX = "META-INF/services/";
//基礎(chǔ)約定接口
private final Class<S> service;
private final ClassLoader loader;
//權(quán)限控制上下文
private final AccessControlContext acc;
//廠商接口實(shí)現(xiàn)類的實(shí)例化對(duì)象集合
private LinkedHashMap<String,S> providers = new LinkedHashMap<>();//以初始化的順序緩存<接口全名稱, 實(shí)現(xiàn)類實(shí)例>
//懶加載迭代器
private LazyIterator lookupIterator

load()初始化

   public void reload() {
        providers.clear();
        lookupIterator = new LazyIterator(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();
    }

load() 方法并沒有實(shí)例化具體實(shí)現(xiàn)類,而是加載需要實(shí)例化的對(duì)象路徑

3.2 實(shí)例化過程

 Class<S> service;//通用接口
 ClassLoader loader;//類加載器
Enumeration<URL> configs = null;//廠商接口文件URL的集合
 Iterator<String> pending = null;//接口具體實(shí)現(xiàn)的路徑類名列表
  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);
            }
        }

hasNext() : 先從provider中查找,如果有,返回true;如果沒有,通過LazyIterator 來進(jìn)行查找. 在 hasNext() 方法中會(huì)獲取當(dāng)前需要實(shí)例化的類名 nextName ,然后在 next() 方法中具體實(shí)例化

next(): 先從provider中直接獲取,如果有,返回實(shí)現(xiàn)類對(duì)象實(shí)例;如果沒有,通過LazyIterator 中 nextService() 來進(jìn)行獲取

 private S nextService() {
            if (!hasNextService()) //獲取nextName 需要加載的類名
                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()); //初始化類并類型轉(zhuǎn)換成Cache對(duì)象
                providers.put(cn, p); 放入實(shí)例化對(duì)象集合中
                return p;
            } catch (Throwable x) {
                fail(service,
                     "Provider " + cn + " could not be instantiated", x);
            }
            throw new Error();          // This cannot happen
        }

上述代碼主要是延遲實(shí)例化類,然后緩存進(jìn)集合,方便下次直接使用

以上就是java框架基礎(chǔ)之SPI機(jī)制實(shí)現(xiàn)及源碼解析的詳細(xì)內(nèi)容,更多關(guān)于java框架基礎(chǔ)SPI機(jī)制的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 解決@NonNull @org.jetbrains.annotations.NotNull報(bào)紅的問題

    解決@NonNull @org.jetbrains.annotations.NotNull報(bào)紅的問題

    這篇文章主要介紹了解決@NonNull @org.jetbrains.annotations.NotNull報(bào)紅的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(48)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(48)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-08-08
  • java整合onlyoffice的各種踩坑記錄

    java整合onlyoffice的各種踩坑記錄

    這篇文章主要給大家介紹了關(guān)于java整合onlyoffice的各種踩坑,OnlyOffice是一種強(qiáng)大的在線協(xié)作軟件,專為企業(yè)和個(gè)人設(shè)計(jì),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • 搭建JavaWeb服務(wù)器步驟詳解

    搭建JavaWeb服務(wù)器步驟詳解

    本篇文章主要給大家詳細(xì)分享了搭建JavaWeb服務(wù)器的詳細(xì)步驟以及用到的代碼,對(duì)此有需要的朋友可以跟著學(xué)習(xí)下。
    2018-02-02
  • SpringBoot底層注解超詳細(xì)介紹

    SpringBoot底層注解超詳細(xì)介紹

    這篇文章主要介紹了SpringBoot底層注解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-09-09
  • Java 日志打印的15個(gè)好建議

    Java 日志打印的15個(gè)好建議

    這篇文章主要介紹了Java日志打印的15個(gè)好建議,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • Java 7菱形語法與泛型構(gòu)造器實(shí)例分析

    Java 7菱形語法與泛型構(gòu)造器實(shí)例分析

    這篇文章主要介紹了Java 7菱形語法與泛型構(gòu)造器,結(jié)合實(shí)例形式分析了Java菱形語法與泛型構(gòu)造器相關(guān)原理與使用技巧,需要的朋友可以參考下
    2019-07-07
  • Springboot實(shí)現(xiàn)全局自定義異常的方法詳解

    Springboot實(shí)現(xiàn)全局自定義異常的方法詳解

    這篇文章主要介紹了Springboot實(shí)現(xiàn)全局自定義異常的方法詳解,SpringBoot的項(xiàng)目已經(jīng)對(duì)有一定的異常處理了,但是對(duì)于我們開發(fā)者而言可能就不太合適了,因此我們需要對(duì)這些異常進(jìn)行統(tǒng)一的捕獲并處理,需要的朋友可以參考下
    2023-11-11
  • 使用Mybatis遇到的there is no getter異常

    使用Mybatis遇到的there is no getter異常

    這篇文章主要介紹了使用Mybatis遇到的there is no getter異常,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • 關(guān)于dubbo的RPC和RESTful性能及對(duì)比

    關(guān)于dubbo的RPC和RESTful性能及對(duì)比

    這篇文章主要介紹了關(guān)于dubbo的RPC和RESTful性能及對(duì)比,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評(píng)論

天峻县| 申扎县| 千阳县| 芒康县| 文水县| 平塘县| 湘乡市| 衡南县| 乐昌市| 精河县| 剑川县| 屯昌县| 正宁县| 海淀区| 云林县| 贵阳市| 南丰县| 天镇县| 都江堰市| 浏阳市| 平阴县| 赞皇县| 盐源县| 德安县| 高碑店市| 思茅市| 定结县| 哈尔滨市| 乐都县| 亚东县| 兴城市| 贡嘎县| 繁昌县| 江油市| 印江| 高唐县| 福建省| 扎兰屯市| 越西县| 衡水市| 梁平县|