目录
SpringApplication::SpringApplication
好久没看SpringBoot了,复习一下,温故而知新。
- @SpringBootApplication
- public class SecurityApplication {
- public static void main(String[] args) {
- SpringApplication.run(SecurityApplication.class,args);
- }
- }
除了注解,就只有一行代码
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
> loadSpringFactories(@Nullable ClassLoader classLoader) { - MultiValueMap
result = cache.get(classLoader); - if (result != null) {
- return result;
- }
-
- try {
- Enumeration
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。
获取监听器的实例对象
分析过程同上
找到当前应用程序的主类,开始执行