91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

發布時間:2021-09-28 09:49:55 來源:億速云 閱讀:221 作者:柒染 欄目:大數據

這篇文章將為大家詳細講解有關如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

    在 SpringBoot中是通過getSpringFactoriesInstances(Class<T> type)方法獲取所有classpath下面的META-INF/spring.factories文件,然后根據type值找到對應的 class  的全限定名稱列表。我來分析一下getSpringFactoriesInstances(Class<T> type)方法是如何工作的

源碼解析

getSpringFactoriesInstances()方法

public class SpringApplication {
   private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
		return getSpringFactoriesInstances(type, new Class<?>[] {});
   }
    // 獲取Spring工廠
   private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
          Class<?>[] parameterTypes, Object... args) {
        // 獲取ClassLoader
       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
       // Use names and ensure unique to protect against duplicates
        // 定義class數組,即返回值 names 是所有 classpath 下面的 META-INF/spring.factories 中定義的父節點(圖2)
       Set<String> names = new LinkedHashSet<>(
         SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        // 內部循環初始化 names的構造函數,獲取實例實例對象(圖2)
       List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
         classLoader, args, names);
       AnnotationAwareOrderComparator.sort(instances);
       return instances;
   }
   // 創建Spring工廠實例
   private <T> List<T> createSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
      Set<String> names) {
      List<T> instances = new ArrayList<>(names.size());
       // 循環處理names的值
      for (String name : names) {
          try { //( 圖3)
             //通過指定的classloader加載對應的類獲取對應的Class對象
             Class<?> instanceClass = ClassUtils.forName(name, classLoader);
             Assert.isAssignable(type, instanceClass);
             Constructor<?> constructor = instanceClass
               .getDeclaredConstructor(parameterTypes);
             //創建一個實例
             T instance = (T) BeanUtils.instantiateClass(constructor, args);
             instances.add(instance);
          } catch (Throwable ex) {
             throw new IllegalArgumentException(
               "Cannot instantiate " + type + " : " + name, ex);
         }
      }
      return instances;
   }
}

    getSpringFactoriesInstances方法通過SpringFactoriesLoader類的loadFactoryNames方法獲取系統加載類去所有classpath下面的 META-INF/spring.factories文件中獲取對應的 class 的全限定名稱結合,在執行createSpringFactoriesInstances方法遍歷該集合對進行循環創建實例。然后返回實例對象集合。

  • names 為獲取所有 classpath 下面的 META-INF/spring.factories文件中applicationContextInitializer相關加載類的值

  • instances 為遍歷names創建的Spring工廠實例列表

以getSpringFactoriesInstances(ApplicationContextInitializer.class)為例進行debug分析

圖1-1和圖1-2標記出所有classpath下面的 META-INF/spring.factories文件中ApplicationContextInitializer.class對應的所有全限定名稱

(圖1-1)

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

(圖1-2)

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

(圖2)根據類名“applicationContextInitializer”獲取 spring.factories文件中applicationContextInitializer相關的工廠類,并進行初始化)

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱 

( 圖3)  根據類名進行初始化創建實例

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

 在SpringApplication類的getSpringFactoriesInstances方法中進入SpringFactoresLoader類的loadFactoryNames方法 

public abstract class SpringFactoriesLoader {
   public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
   private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
    // 加載工廠
   public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
      // 獲取類名稱(圖4)
      String factoryClassName = factoryClass.getName();
      // 根據類名稱獲取需要加載的工廠類名稱
      return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
   }
    // 通過加載所有 classpath 下面的 META-INF/spring.factories文件,掃描加載類,(圖8)
   private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        // 從cache獲取實例的結果集 當是Null表示當前的cache是空的;cache 實現 new ConcurrentReferenceHashMap<>()
      MultiValueMap<String, String> result = cache.get(classLoader);
      if (result != null) {
         return result;
      }
      try {
          // 獲取所有 classpath 下面的 META-INF/spring.factories 中的資源 urls(圖5)
          // 當classLoader為非空的時候調用getResouurces方法獲取
          // 當classLoader為空的時候調用ClassLoader.getSystemResouurces方法獲取
         Enumeration<URL> urls = (classLoader != null ?
               classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
               ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
         result = new LinkedMultiValueMap<>();
          // 循環處理 urls中的元素,獲取元素 
         while (urls.hasMoreElements()) {
             // 獲取元素 url地址(圖6) 
            URL url = urls.nextElement();
            UrlResource resource = new UrlResource(url);
             // 解析文件 把文件變成配置屬性(圖6)
            Properties properties = PropertiesLoaderUtils.loadProperties(resource);
             // 循環解析并把結果放入result
            for (Map.Entry<?, ?> entry : properties.entrySet()) {
                // 類名列表(圖7)
               List<String> factoryClassNames = Arrays.asList(
                     StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
               result.addAll((String) entry.getKey(), factoryClassNames);
            }
         }
          // 緩存類加載器和文件解析器的結果集
         cache.put(classLoader, result);
         return result;
      }
      catch (IOException ex) {
         throw new IllegalArgumentException("Unable to load factories from location [" +
               FACTORIES_RESOURCE_LOCATION + "]", ex);
      }
   }
}

 以loadFactoryNames(ApplicationContextInitializer.class,classLoader)為例進行debug分析

(圖4)獲取class全稱

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

(圖5) 獲取所有 classpath 下面的 META-INF/spring.factories文件的urls

如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

(圖6) 獲取spring.factories文件的具體位置及文件中的內容)如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱(圖7) 獲取spring.factories文件內容中的對應類列表如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱

( 圖8)

總結

    通過classLoader加載classpath下面的META-INF/spring.factories文件,獲取文件信息解析成配置屬性存入結果集中,在根據type的全限定名稱,從結果集中獲取type對應的結果集。循環便利該結果集根據“全限定名稱”創建實例。對實例集合排序后返回

關于如何理解springboot2.0.6中META-INF/spring.factories通過系統加載類獲取對應的class的全限定名稱就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

资溪县| 霍林郭勒市| 建始县| 克拉玛依市| 白山市| 洪雅县| 沭阳县| 龙陵县| 朝阳市| 肃南| 永丰县| 焦作市| 余干县| 平乡县| 黄龙县| 开封市| 山西省| 潢川县| 保定市| 旺苍县| 饶河县| 金沙县| 枞阳县| 康定县| 忻州市| 延津县| 宁津县| 汉中市| 甘肃省| 甘孜县| 锦屏县| 东明县| 桂林市| 泸水县| 南充市| 广东省| 三亚市| 公安县| 横峰县| 杂多县| 洛阳市|