SpringBoot启动运行流程

SpringBoot启动运行流程

SpringBoot有两种启动方式:

  • 第一种方式:通过调用SpringApplication的静态方法run方法启动
@SpringBootApplication
public class Application {
   

    public static void main(String[] args) {
   
        SpringApplication.run(Application.class, args);
    }

}
  • 第二种方式:通过SpringApplication实例调用run方法启动
@SpringBootApplication
public class App {
   

    public static void main(String[] args) {
   
        SpringApplication springApplication = new SpringApplication(App.class);
        ConfigurableApplicationContext context = springApplication.run(args);
        context.close();
    }
}

而调用静态方法run方法,底层其实也是创建SpringApplication对象的方式。接下来就从创建SpringApplication实例开始梳理一下SpringBoot的启动运行流程。

1. 调用构造函数

@SuppressWarnings({
    "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   
   this.resourceLoader = resourceLoader;
   //1.1 启动传入源非空判断,如以上示例中传入的App.class
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
   //1.2 推断web应用类型
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
   //1.3 加载所有classpath下面的META-INF/spring.factories中配置的ApplicationContextInitializer
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
   //1.4 加载所有classpath下面的META-INF/spring.factories中配置的ApplicationListener
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   //1.5 推断main方法所在的类
   this.mainApplicationClass = deduceMainApplicationClass();
}
1.1 源非空判断

调用构造函数时,传入源进行非空判断,如以上示例中传入的App.class。

1.2 推断web应用类型
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;
}
private static final String[] SERVLET_INDICATOR_CLASSES = {
    "javax.servlet.Servlet",
      "org.springframework.web.context.ConfigurableWebApplicationContext" };

private static final String WEBMVC_INDICATOR_CLASS = "org.springframework." + "web.servlet.DispatcherServlet";

private static final String WEBFLUX_INDICATOR_CLASS = "org." + "springframework.web.reactive.DispatcherHandler";

private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";

  根据源码,这里提供三种应用类型:
  REACTIVE—Reactor编程模型的非阻塞异步Web编程框架WebFlux;
  SERVLET—运行在Servlet容器上;
  NONE—非web应用。
  通过类路径下的是否存在相应的类判断具体的应用程序类型:

REACTIVE:org.springframework.web.reactive.DispatcherHandler
SERVLET:org.springframework.web.servlet.DispatcherServlet,org.glassfish.jersey.servlet.ServletContainer
NONE:javax.servlet.Servletorg.springframework.web.context.ConfigurableWebApplicationContext
1.3 加载ApplicationContextInitializer

加载所有classpath下面的META-INF/spring.factories中配置的ApplicationContextInitializer。
ApplicationContextInitializer接口使用,可参见文章:https://blog.csdn.net/qq_35006663/article/details/102265276

1.4 加载ApplicationListener

加载所有classpath下面的META-INF/spring.factories中配置的ApplicationListener。
ApplicationListener接口使用,可参见文章:https://blog.csdn.net/qq_35006663/article/details/101039761

1.5 推断main方法所在的类

找到项目中的main方法所在的类,即启动类。

private Class<?> deduceMainApplicationClass() {
   
	try {
   
		StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
		for (StackTrac
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值