目录
SpringApplication::SpringApplication
好久没看SpringBoot了,复习一下,温故而知新。
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class,args);
}
}
注解
- 声明是一个spring应用程序配置类
- 把这个类加载到ioc容器中去,完成包扫描
- 导入配置类
- 根据定义的扫描路径,把符合扫描规则的类装配到spring容器中
SpringApplication::SpringApplication
除了注解,就只有一行代码
SpringApplication.run(SecurityApplication.class,args);
我们来分析run方法,点进去看到
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
我们先分析
(new SpringApplication(primarySources))
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 壹
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 贰
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 叁
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 肆
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 伍
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 陆
this.mainApplicationClass = deduceMainApplicationClass();
}
壹
配置resourceLoader
贰
配置主启动类
叁
判断当前应用程序的类型。
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
根据Class是否存在而去判断应用程序类型(反射)。
肆
获取初始化器的实例对象
(Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)往代码里边点,走到
loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
第一步:我们来看loadSpringFactories(classLoader)
主要从META-INF/spring.factories中获取需要加载的类(去重),并且最后放入缓存中
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
cache.put(classLoader, result);
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
第二步我们来看getOrDefault(factoryTypeName, Collections.emptyList()):
从map中取出来key为ApplicationContextInitializer的value。
伍
获取监听器的实例对象
分析过程同上
陆
找到当前应用程序的主类,开始执行