springboot启动逻辑分析一-------new SpringApplication()

Posted itivy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot启动逻辑分析一-------new SpringApplication()相关的知识,希望对你有一定的参考价值。

	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
          this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//(1).根据classpath中的存在的类推断应用类型 this.webApplicationType = WebApplicationType.deduceFromClasspath();
          //(2).获取ApplicationContextInitializer,并设置到Initializers中 setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class));
          //(3).获取ApplicationContextInitializer,并设置到Initializers中 setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
          //(4).推断主类 this.mainApplicationClass = deduceMainApplicationClass(); }

(1).推断应用类型

		this.webApplicationType = WebApplicationType.deduceFromClasspath();

  

	static WebApplicationType deduceFromClasspath() {
          //springframework.web.reactive.DispatcherHandler类
          //但是不存在org.springframework.web.servlet.DispatcherServlet和org.glassfish.jersey.servlet.ServletContainer类
          //返回WebApplicationType.REACTIVE类型
		if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
				&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
			return WebApplicationType.REACTIVE;
		}
          //不存在javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext

          //返回WebApplicationType.NONE

		for (String className : SERVLET_INDICATOR_CLASSES) {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
		}
		return WebApplicationType.SERVLET;
	}

  

static WebApplicationType deduceFromClasspath() {
  //springframework.web.reactive.DispatcherHandler类
  //但是不存在org.springframework.web.servlet.DispatcherServlet和org.glassfish.jersey.servlet.ServletContainer类
  //返回WebApplicationType.REACTIVE类型
  if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
    && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null) 
    && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null))
  {
    return WebApplicationType.REACTIVE;
  }
  //不存在javax.servlet.Servlet和org.springframework.web.context.ConfigurableWebApplicationContext
  //返回WebApplicationType.NONE
  for (String className : SERVLET_INDICATOR_CLASSES)
  {
    if (!ClassUtils.isPresent(className, null))
    {
      return WebApplicationType.NONE; 
    }
  }
  //否则返回WebApplicationType.SERVLET
  return WebApplicationType.SERVLET;
} 

(2)设置Initializers

		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));

 

	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
		return getSpringFactoriesInstances(type, new Class<?>[] {});
	}
	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
			Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		// Use names and ensure unique to protect against duplicates
		Set<String> names = new LinkedHashSet<>(
				SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
				classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

  

setInitializers((Collection) getSpringFactoriesInstances( //(2).初始ApplicationContextInitializer
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); //(3).确定ApplicationListener
this.mainApplicationClass = deduceMainApplicationClass(); //(4).确定mainApplicationClass
(1).推断应用类型,依据判断classPath是否存在
this.webApplicationType = WebApplicationType.deduceFromClasspath();
(2).确定ApplicationContextInitializer,目的待定,重点是读取classpath下的META-INF/spring.factories,并缓存
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
(3).确定ApplicationListener,目的待定,重点是读取classpath下的META-INF/spring.factories,并缓存
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
(4).确定mainApplicationClass,重点new RuntimeException().getStackTrace()可以获取堆栈
this.mainApplicationClass = deduceMainApplicationClass();

以上是关于springboot启动逻辑分析一-------new SpringApplication()的主要内容,如果未能解决你的问题,请参考以下文章

源码分析|SpringBoot启动流程

SpringBoot启动流程

如何在 springboot 启动之后 执行一段逻辑?

spring boot启动原理步骤分析

深入springboot原理——一步步分析springboot启动机制(starter机制)

深入springboot原理——一步步分析springboot启动机制(starter机制)