SpringBoot启动流程源码分析( 二 )

  • 推断web应用类型
  • 通过加载类路径目录META-INF下的spring.factories文件读取出初始化器和监听器集合并设置到SpringApplication实例对应的初始化器和监听器属性列表中
  • 推断主启动类并赋值给SpringApplication启动类的mainApplicationClass属性
  • 推断Web应用类型进入WebApplicationType#deduceFromClasspath方法
    private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};static WebApplicationType deduceFromClasspath() {if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {return REACTIVE;} else {String[] var0 = SERVLET_INDICATOR_CLASSES;int var1 = var0.length;for(int var2 = 0; var2 < var1; ++var2) {String className = var0[var2];if (!ClassUtils.isPresent(className, (ClassLoader)null)) {return NONE;}}return SERVLET;}}复制
    • 若满足类路径(包括依赖jar包)中存在org.springframework.web.reactive.DispatcherHandler类 , 同时不存在org.springframework.web.servlet.DispatcherServlet类和org.glassfish.jersey.servlet.ServletContainer类则返回REACTIVE类型Web应用
    • 遍历判断类路径中是否同时存在javax.servlet.Servlet类和org.springframework.web.context.ConfigurableWebApplicationContext类 , 满足则返回SERVLET类型Web应用 , 否则返回非Web应用
    加载spring.factories文件中配置的初始化器和监听器通过调用SpringApplication#getSpringFactoriesInstances方法得到的返回值设置初始化器和监听器属性 , 传入的参数分别为ApplicationContextInitializer类和ApplicationListener
    /***根据传入的type参数获取类路径META-INF/spring.factories文件中的自动配置初始化类集合@param type 类型@return Collection<T> 泛型集合*/private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return this.getSpringFactoriesInstances(type, new Class[0]);}/***上一个方法的多参数重载方法* @param type 类型* @param parameterTypes 参数类型数组* @param args 参数数组*/private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = this.getClassLoader();// 通过SpringFactoriesLoader#loadFactoryNames方法获取Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass.getName();return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, 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 {// 缓存中没有则去META-INF/spring.factories文件中加载并读取解析try {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);Properties properties = PropertiesLoaderUtils.loadProperties(resource);Iterator var6 = properties.entrySet().iterator();while(var6.hasNext()) {Entry<?, ?> entry = (Entry)var6.next();String factoryClassName = ((String)entry.getKey()).trim();String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());int var10 = var9.length;for(int var11 = 0; var11 < var10; ++var11) {String factoryName = var9[var11];result.add(factoryClassName, factoryName.trim());}}}cache.put(classLoader, result);return result;} catch (IOException var13) {throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);}}}/*** 创建spring.factories文件中的初始化类实例集合*/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.factories文件中的初始化类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;}

    经验总结扩展阅读