ServiceLoader整理

ServiceLoader整理

  • ServiceLoader簡單使用
    Search search = null; ServiceLoader<Search> serviceLoader = ServiceLoader.load(Search.class); Iterator<Search> searchs = serviceLoader.iterator(); if (searchs.hasNext()) { search = searchs.next(); }

  • 源碼分析

    • ServiceLoader.load
      • public static <S> ServiceLoader<S> load(Class<S> service) {
        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        return ServiceLoader.load(service, cl);
        }
        public static <S> ServiceLoader<S> load(Class<S> service, ClassLoader loader)
        {
        return new ServiceLoader<>(service, loader);
        }
        private ServiceLoader(Class<S> svc, ClassLoader cl) {
        service = svc;
        loader = cl;
        reload();
        }
        public void reload() {
        providers.clear();//private LinkedHashMap<String,S> providers = new LinkedHashMap<>();
        lookupIterator = new LazyIterator(service, loader);
        }
        private class LazyIterator implements Iterator<S>//這里叫l(wèi)azy其實(shí)就是調(diào)用hasNext的時(shí)候才去加載
        {
        ...
        private LazyIterator(Class<S> service, ClassLoader loader) {
        this.service = service;
        this.loader = loader;
        }
        ...
        }
    • iterator()
      • public Iterator<S> iterator() {
          return new Iterator<S>() {//返回匿名內(nèi)部類
              Iterator<Map.Entry<String,S>> knownProviders = providers.entrySet().iterator();//目前這個(gè)linkedhashmap還是空的
              public boolean hasNext() {
                  if (knownProviders.hasNext())
                      return true;
                  return lookupIterator.hasNext();//knownProviders空時(shí)走這個(gè)
              }
              public S next() {
                  if (knownProviders.hasNext())
                      return knownProviders.next().getValue();
                  return lookupIterator.next();
              }
              public void remove() {
                  throw new UnsupportedOperationException();
              }
          };
        
        }
    • hasNext()
      • public boolean hasNext() {
        if (nextName != null) {//null 調(diào)用next后會(huì)置nextName為null,不調(diào)用next則nextName始終不為null
        return true;
        }
        if (configs == null) {//null
        try {
        String fullName = PREFIX + service.getName();
        if (loader == null)//null
        configs = ClassLoader.getSystemResources(fullName);
        else
        //這里加載資源: META-INF/services/packageName.className
        //Finds all the resources with the given name.
        //A resource is some data (images, audio, text, etc) that can be accessed by class code in a way that is independent of the location of the code.
        configs = loader.getResources(fullName);
        } catch (IOException x) {
        fail(service, "Error locating configuration files", x);
        }
        }
        while ((pending == null) || !pending.hasNext()) {//null
        if (!configs.hasMoreElements()) {
        return false;
        }
        pending = parse(service, configs.nextElement());//go here
        }
        nextName = pending.next();// Iterator<String> pending
        return true;
        }
      • private Iterator<String> parse(Class service, URL u)throws ServiceConfigurationError
        {
        InputStream in = null;
        BufferedReader r = null;
        ArrayList<String> 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);
        }
        }
        return names.iterator();
        }
    • next()
      • public S next() {
        if (!hasNext()) {
        throw new NoSuchElementException();
        }
        String cn = nextName;
        nextName = null;// *** 置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());// Casts an object to the class or interface represented by this Class object
        providers.put(cn, p);// add cache 放入到knownProviders里面
        return p;
        } catch (Throwable x) {
        fail(service, "Provider " + cn + " could not be instantiated: " + x, x);
        }
        throw new Error();// This cannot happen
        }
    • 小結(jié)
      • hasNext和next必須搭配一起使用
        • hasNext獲取nextName從一個(gè)Iterator<String>的pending中
        • next則拿這個(gè)nextName去加載創(chuàng)建Class并創(chuàng)建對(duì)象返回
      • 首次從lookupIterator中獲取,后面從knownProviders緩存里面獲取
  • References

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,706評(píng)論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評(píng)論 19 139
  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗(yàn)。 張土汪:刷leetcod...
    土汪閱讀 12,921評(píng)論 0 33
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 4,012評(píng)論 0 11
  • 一首老歌,在你我揮手說再見的舊址,安靜地跌落。 ——楔子 天涯逢秋,蒼茶漸染! 日月呼嘯,旋轉(zhuǎn)得倉促,注定了: 一...
    玨詩閱讀 410評(píng)論 0 0

友情鏈接更多精彩內(nèi)容