------本文只作为跟代码的一个参考,建议可以根据思路在指定类中断点调试学习----
1、运行被@SpringBootApplication修饰的程序入口,执行main方法,调用SpringApplication的静态run方法,返回ConfigurableApplicationContext。
2、在SpringApplication的静态run方法中创建了以启动类为参数的SpringApplication对象并调用了非静态run方法,构造方法和run方法内容如下
1)首先解析SpringApplication构造方法的操作:
public SpringApplication(Class<?>... primarySources) { this((ResourceLoader)null, primarySources); } 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; // PrimarySources 启动类class对象 Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); // 判断是否使用servlet容器启动,是否选择内置的servlet容器。SERVLET使用内嵌容器启动 this.webApplicationType = WebApplicationType.deduceFromClasspath(); // 通过读取META-INF/spring.factories配置创建springboot启动的初试化对象 this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 初始化监听类 this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = this.deduceMainApplicationClass(); } 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) { ClassLoader classLoader = this.getClassLoader(); //使用工厂加载类读取spring.factories文件中配置的接口实现类的全限定名list Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); //使用反射根据全限定名执行构造方法生成对象 List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); // 根据实现的Ordered接口,实现getOrder返回的int值排序。没有实现这个接口的类不参与排序,原位置不变 AnnotationAwareOrderComparator.sort(instances); return instances; } 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 { 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; }
SpringFactoriesLoader.loadFactoryNames(type, classLoader)源码如下:
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { String factoryTypeName = factoryType.getName(); return (List)loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList()); } private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); //底层封装的是LinkedHashMap,并对add方法进行了重写,保证从不同路径下的spring.factories读取到的同一个key都会在不同循环中都放在同一个key的value中,不会发生覆盖 LinkedMultiValueMap result = new LinkedMultiValueMap(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); // PropertiesLoaderUtils,spring的工具类,将配置文件流写入hashTable子类properties实例中--操作过程中只区分了是不是xml文件 Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); 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); } } }
public void add(K key, @Nullable V value) { List<V> values = (List)this.targetMap.computeIfAbsent(key, (k) -> { return new LinkedList(); }); values.add(value); }