调用静态方法启动

  1. SpringApplication.run();

通过构造方法创建SpringApplication类

  1. new SpringApplication(primarySources).run(args)

SpringApplication类的构造方法

  1. /**
  2. * Create a new {@link SpringApplication} instance. The application context will load
  3. * beans from the specified primary sources (see {@link SpringApplication class-level}
  4. * documentation for details. The instance can be customized before calling
  5. * {@link #run(String...)}.
  6. * @param resourceLoader the resource loader to use
  7. * @param primarySources the primary bean sources
  8. * @see #run(Class, String[])
  9. * @see #setSources(Set)
  10. */
  11. @SuppressWarnings({ "unchecked", "rawtypes" })
  12. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  13. this.resourceLoader = resourceLoader;
  14. Assert.notNull(primarySources, "PrimarySources must not be null");
  15. this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  16. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  17. setInitializers((Collection) getSpringFactoriesInstances(
  18. ApplicationContextInitializer.class));
  19. setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  20. this.mainApplicationClass = deduceMainApplicationClass();
  21. }

Web类型推断

先判断是不是Reactive,然后如果没有Servlet相关类则不是Web类型,否则是Servlet类型。

  1. WebApplicationType.deduceFromClasspath();
  1. private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
  2. "org.springframework.web.context.ConfigurableWebApplicationContext" };
  3. private static final String WEBMVC_INDICATOR_CLASS = "org.springframework."
  4. + "web.servlet.DispatcherServlet";
  5. private static final String WEBFLUX_INDICATOR_CLASS = "org."
  6. + "springframework.web.reactive.DispatcherHandler";
  7. private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
  8. private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
  9. private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
  10. static WebApplicationType deduceFromClasspath() {
  11. if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
  12. && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
  13. && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
  14. return WebApplicationType.REACTIVE;
  15. }
  16. for (String className : SERVLET_INDICATOR_CLASSES) {
  17. if (!ClassUtils.isPresent(className, null)) {
  18. return WebApplicationType.NONE;
  19. }
  20. }
  21. return WebApplicationType.SERVLET;
  22. }

对SpringFactories的处理

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, Object... args) {
   ClassLoader classLoader = getClassLoader();
   // Use names and ensure unique to protect against duplicates
   //按照class类型获取需要加载的类的名称
   Set<String> names = new LinkedHashSet<>(
         SpringFactoriesLoader.loadFactoryNames(type, classLoader));
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
         classLoader, args, names);
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

获取需要实例化的对象名称

SpringFactoriesLoader.class

/**
 * The location to look for factories.
 * <p>Can be present in multiple JAR files.
 */
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();

/**
 * Load the fully qualified class names of factory implementations of the
 * given type from {@value #FACTORIES_RESOURCE_LOCATION}, using the given
 * class loader.
 * @param factoryClass the interface or abstract class representing the factory
 * @param classLoader the ClassLoader to use for loading resources; can be
 * {@code null} to use the default
 * @throws IllegalArgumentException if an error occurs while loading factory names
 * @see #loadFactories
 */
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
   String factoryClassName = factoryClass.getName();
   return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
   //根据classloader查看缓存中是否包含需要的对象名称
   MultiValueMap<String, String> result = cache.get(classLoader);
   if (result != null) {
      return result;
   }
    //下面的方法只执行一次,后面就从缓存中获取
   try {
       //加载META-INF下的spring.factories文件
      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 factoryClassName = ((String) entry.getKey()).trim();
            for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
               //添加类型对应的所有需要加载的类的名称
               result.add(factoryClassName, factoryName.trim());
            }
         }
      }
      //将classloader作为key放入缓存中,等待下一次直接调用
      cache.put(classLoader, result);
      return result;
   }
   catch (IOException ex) {
      throw new IllegalArgumentException("Unable to load factories from location [" +
            FACTORIES_RESOURCE_LOCATION + "]", ex);
   }
}

实例化对象

createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
      Set<String> names) {
   List<T> instances = new ArrayList<>(names.size());
   for (String name : names) {
      try {
         Class<?> instanceClass = ClassUtils.forName(name, classLoader);
         Assert.isAssignable(type, instanceClass);
         //获得构造器时,会校验传入的参数类型和对象的构造函数的参数类型是否匹配
         Constructor<?> constructor = instanceClass
               .getDeclaredConstructor(parameterTypes);
         T instance = (T) BeanUtils.instantiateClass(constructor, args);
         instances.add(instance);
      }
      catch (Throwable ex) {
         throw new IllegalArgumentException(
               "Cannot instantiate " + type + " : " + name, ex);
      }
   }
   return instances;
}

推断主类

通过堆栈信息判断主类。

private Class<?> deduceMainApplicationClass() {
   try {
      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
      for (StackTraceElement stackTraceElement : stackTrace) {
         if ("main".equals(stackTraceElement.getMethodName())) {
            return Class.forName(stackTraceElement.getClassName());
         }
      }
   }
   catch (ClassNotFoundException ex) {
      // Swallow and continue
   }
   return null;
}