上一章分析到類加載器
首先獲取當前線程的類加載器,這裏有個雙親委派機制,大家可以自己搜下看下。這個不是重點就不多介紹了。這個方法就是查找類加載器
我們繼續上一次的分析
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可以自行百度下是什麼東東
先到這裏下一篇繼續