springboot 源碼解析(2)

上一章分析到類加載器

首先獲取當前線程的類加載器,這裏有個雙親委派機制,大家可以自己搜下看下。這個不是重點就不多介紹了。這個方法就是查找類加載器

我們繼續上一次的分析

Set<String> names = new LinkedHashSet<>(
      SpringFactoriesLoader.loadFactoryNames(type, classLoader));
SpringFactoriesLoader.loadFactoryNames(type, classLoader)

這個type我們知道他是

ApplicationContextInitializer類

String factoryClassName = factoryClass.getName();拿到org.springframework.context.ApplicationContextInitializer
loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList())

鏈式調用方法。我們先看第一個loadSpringFactories

MultiValueMap<String, String> result = cache.get(classLoader); 看這個意思從cache中先獲取當前的類加載器加載過的MultiValueMap這個類型的map跟我們平時見到的不太一樣,。他是可以一個key對應多個value的

如果不爲空直接返回

爲空繼續往下走

Enumeration<URL> urls = (classLoader != null ?
      classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
      ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));

 

我們看看spring.factories裏面都有什麼

我們看到他定義了一些類

然後我們繼續往下看

while (urls.hasMoreElements()) {
   URL url = urls.nextElement();
   UrlResource resource = new UrlResource(url);
   Properties properties = PropertiesLoaderUtils.loadProperties(resource);
   for (Map.Entry<?, ?> entry : properties.entrySet()) {
      String factoryClassName = ((String) entry.getKey()).trim();
      for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
         result.add(factoryClassName, factoryName.trim());
      }
   }
}
cache.put(classLoader, result);

大體意思就是循環上面找到的文件,讀取文件裏面的配置信息放到map中加入緩存

.getOrDefault(factoryClassName, Collections.emptyList());  獲取org.springframework.context.ApplicationContextInitializer對應的類

發現有7個需要初始化的類

繼續回到上面的方法

List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
      classLoader, args, names);

開始初始化工廠

循環names就是上面的7個配置文件的類

Class<?> instanceClass = ClassUtils.forName(name, classLoader);

用之前的類加載器加載類,我們跟進去看

這個有點長,我們分段看

第一步斷言判斷是不是空不多說了

第二步

resolvePrimitiveClassName我們跟進去

這個感覺他就判斷了一下長度小於8就從一個map中獲取。我們看下map是個什麼東東

吆喝。他放了一下基礎的封裝類型進去。爲什麼這麼做那?其實我們知道。自己命名的一般都比較長加上包名基本不會少於8,這麼做的話可以快速取到類型,佩服佩服

繼續往下

if (clazz == null) {
   clazz = commonClassCache.get(name);
}
if (clazz != null) {
   return clazz;
}

如果上面沒有取到,從緩存中取,如果不爲空返回

繼續往下

if (name.endsWith(ARRAY_SUFFIX)) {
   String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
   Class<?> elementClass = forName(elementClassName, classLoader);
   return Array.newInstance(elementClass, 0).getClass();
}
public static final String ARRAY_SUFFIX = "[]";

如果是個數組

先截取然後再創建對象 轉換成數組

再往下

if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
   String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
   Class<?> elementClass = forName(elementName, classLoader);
   return Array.newInstance(elementClass, 0).getClass();
}
private static final String NON_PRIMITIVE_ARRAY_PREFIX = "[L";

如果是一維數組

跟上面一樣


 

 

然後繼續返回來看

Assert.isAssignable(type, instanceClass);再次斷言判斷是不是一個類型,多麼嚴謹,不相信任何人,自己都判斷。
Constructor<?> constructor = instanceClass
      .getDeclaredConstructor(parameterTypes); 獲取構造器,類的構造方法
T instance = (T) BeanUtils.instantiateClass(constructor, args);

根據構造方法實例化對象

我們看看他如何跟進構造方法實例化的

ReflectionUtils.makeAccessible(ctor);檢查構造方法是不是私有的
return KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ? BeanUtils.KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args);

判斷類是不是Kotlin類型的如果是Kotlin類型的用Kotlin類初始化。否則直接生成對象返回

Kotlin可以自行百度下是什麼東東

先到這裏下一篇繼續

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章