此博客基于spring 2.3.5.RELEASE版本调试,每个版本代码不同
第一步:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
第二步:新建一个SpringApplication对象
//primarySources就是刚才传进来的类名:DemoApplication.class
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
第三步:ResourceLoader资源加载器,在这个地方传的是null,后面会判断是否为空,如果为空,则调用默认的
public SpringApplication(Class<?>... primarySources) {
this((ResourceLoader)null, primarySources);
}
第四步:
//resourceLoader为空,primarySources就是之前传入的DemoApplication.class
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//下面这部分是设置默认属性值
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//下面这两个方法是核心方法
//获取ApplicationContextInitializer,也是在这里开始首次加载spring.factories文件
//下面代码中getSpringFactoriesInstances方法会加载META-INF/spring.factories文件,
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//获取监听器,这里是第二次加载spring.factories文件
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
第4.1步:先来分析setInitializers方法
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return this.getSpringFactoriesInstances(type, new Class[0]);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
//注意:此时的类加载是空的,因为之前传入的是null
ClassLoader classLoader = this.getClassLoader();
//获取spring.factory中key为ApplicationContextInitializer的value集合
/*
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
*/
Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//根据上面获取到的资源文件的名字,通过反射进行实例化
//type:ApplicationContextInitializer.class
//parameterTypes:null
//classLoader:刚才拿到的默认的
//args:null
//数组
List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
//排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
getClassLoader方法详解
//如果类加载器为null,则调用ClassUtils.getDefaultClassLoader()的默认类加载器
public ClassLoader getClassLoader() {
return this.resourceLoader != null ? this.resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader();
}
SpringFactoriesLoader.loadFactoryNames()方法详解
//资源文件加载器,用来加载资源文件,spring.factory
//下面代码中getSpringFactoriesInstances方法会加载META-INF/spring.factories文件,
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
//factoryType是ApplicationContextInitializer.class
//factoryTypeName是之前传入的ApplicationContextInitializer的权限定类名
String factoryTypeName = factoryType.getName();
//加载资源文件,获取到spring.factories文件中所有的key-value信息
//getOrDefault:通过ApplicationContextInitializer获取spring.factories中的value信息,获取不到,就返回一个null集合
/*
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
*/
return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}
loadSpringFactories()方法详解:
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
//此时cache中是空的,读取完磁盘上的资源文件之后会缓存到cashe中
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
//加载META-INF/spring.factories里面的资源
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
//通过属性加载器的工具类加载spring.factories里面的key-value键值对
Properties properties =
PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
//var6是key-value键值对
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
//获取key的名字
String factoryTypeName = ((String)entry.getKey()).trim();
//使用“,”分割转数组方式获取里面的值
String[] var9 =
StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryImplementationName = var9[var11];
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
//保存到缓存中
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
createSpringFactoriesInstances()方法详解
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList(names.size());
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
//通过前面从spring.factory中获取到的org.springframework.context.ApplicationContextInitializer=...的key-value键值对中的name,用反射进行实例化
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
//获取构造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
//实例化对象
T instance = BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable var12) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
}
}
return instances;
}
第4.2步:setListeners()方法详解
同上,获取spring.factory中key为ApplicationListener的集合,并进行实例化