题记

在使用SpringBoot过程中,我们只需要引入相关依赖,然后在main方法中调用SpringBootApplication.run(应用程序启动类.class)方法即可,无需在配置文件中指定当前运行环境(Servlet or Rective),那么SpringBoot是如何确定当前运行环境呢?是Servlet还是Reactive?

问题的答案需要我们从SpringBoot源码中找到(源码版本为2.3.0)。

源码分析

首先从SpringApplication.run()方法着手。

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

在该方法中调用了重载的run方法。

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);
}

而在重载的run方法中,首先通过SpringApplication的有参构造函数来创建实例,然后调用其run方法并返回。

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);
}

和之前一样,在一个参数的SpringApplication的构造函数中调用了重载的构造函数。

public SpringApplication(Class<?>... primarySources) {this(null, primarySources);
}

在该构造函数中完成了SpringApplication的初始化,其中调用的WebApplicationType的deduceFromClasspath方法就是根据当前类路径来推断要使用何种运行环境。

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null");this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));// 根据当前类路径来推断要使用何种运行环境this.webApplicationType = WebApplicationType.deduceFromClasspath();setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();
}

因此,本次分析重点就是该deduceFromClasspath方法。在分析该方法前,我们首先来看下在WebApplicationType类中定义的4个常量:SERVELT_INDICATOR_CLASSES、WEBMVC_INDICATOR_CLASS、WEBFLUX_INDICATOR_CLASS、JERSEY_INDICATOR_CLASS。这4个常量的值都是某个类或者某些类的全限定名,例如SpringMVC的DispatcherServlet,WebFlux的DispatcherHandler。

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";

熟悉前面那4个变量值后,接下来我们再来分析deduceFromClasspath方法就会很容易。

// org.springframework.boot.WebApplicationType#deduceFromClasspath
static WebApplicationType deduceFromClasspath() {// 类路径下存在DispatcherHandler并且不存在DispatcherServlet并且不存在ServletContainer。如果这三个条件成立,则决定当前应用的运行环境为Reactive。if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {return WebApplicationType.REACTIVE;}// Servlet不存在并且ConfigurableWebApplicationContext也不存在,则决定不使用任何环境(非Servlet,非Reactive)for (String className : SERVLET_INDICATOR_CLASSES) {if (!ClassUtils.isPresent(className, null)) {return WebApplicationType.NONE;}}// 最后,决定当前应用使用Servlet环境return WebApplicationType.SERVLET;
}

总结

通过以上分析我们可以得知,SpringBoot推断当前应用使用何种环境是根据类路径下存不存在某些指定的类来决定。这点和条件注解@ConditionOnClass或@ConditionOnMissingClass实现基本差不多,我们也可以通过借鉴这种思路在日常开发中来自动启用/关闭一些属性配置。

小知识-Spring Boot是如何确定当前运行环境相关推荐

  1. Micronaut for Spring支持Spring Boot应用以Micronaut形式运行

    在Micronaut 1.0.1小版本发布的同时,Object Computing, Inc.(OCI)还发布了Micronaut for Spring 1.0 M1.在发布说明中这样写到: Micr ...

  2. 面试官:为什么 Spring Boot 的 jar 可以直接运行

    转载自  面试官:为什么 Spring Boot 的 jar 可以直接运行 来源:Gormat's Notes fangjian0423.github.io/2017/05/31/springboot ...

  3. Spring Boot 2.0系列文章(四):Spring Boot 2.0 源码阅读环境搭建

    前提 前几天面试的时候,被问过 Spring Boot 的自动配置源码怎么实现的,没看过源码的我只能投降��了. 这不,赶紧来补补了,所以才有了这篇文章的出现,Spring Boot 2. 0 源码阅 ...

  4. 小程序+spring boot校园交友平台毕业设计-附源码191733

    摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,校园交友小程序被用户普遍使用,为方便用户能够 ...

  5. 小程序+spring boot校园二手交易平台 毕业设计-附源码191637

    Springboot校园二手交易平台小程序 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最 ...

  6. (附源码)小程序+spring boot校园二手交易平台 毕业设计 191637

    Springboot校园二手交易平台小程序 摘 要 信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最 ...

  7. 小程序+spring boot记账微信小程序 毕业设计-附源码180815

    记账微信小程序 摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,记账微信小程序被用户普遍使用 ...

  8. 小程序+spring boot心理测评与活动管理系统毕业设计-附源码191752

    摘  要 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,心理测评与活动管理小程序被用户普遍使用,为方 ...

  9. 小程序+spring boot美食教程小程序 毕业设计-附源码190900

    Springboot美食教程小程序的设计与实现 摘 要 本文设计了一种基于微信小程序的美食教程小程序,系统为人们提供了方便快捷.即用即搜的美食教程服务,包括美食资讯.美食话题.注册登录等,用户能够方便 ...

  10. (附源码)mysql小程序+spring boot美食教程小程序 毕业设计 190900

    Springboot美食教程小程序的设计与实现 摘 要 本文设计了一种基于微信小程序的美食教程小程序,系统为人们提供了方便快捷.即用即搜的美食教程服务,包括美食资讯.美食话题.注册登录等,用户能够方便 ...

最新文章

  1. 苹果智能车芯片已基本就绪!最新造车进展曝光,股价一夜暴涨4000亿
  2. 前端一HTML:八:css中与文本相关的属性
  3. 15条走红网络的手机摄影技巧
  4. Linux C : Makefile 的编写和示例
  5. SAP Fiori 修改catalog group名称的技术实现
  6. quartz mysql 初始化_quartz scheduler 从数据库初始化
  7. 远程连接:hive 报错:Permission denied: user=anonymous, access=EXECUTE
  8. 微信打击违规贷款、仿冒公众号等行为 累积处罚3万多个公众号
  9. 问题记录_MFC使用不了using namespace std
  10. 将指定内容写入目标文件(日志)
  11. 比较经典的java程序_一些经典的java小程序代码,最好能复制后直接使用的 爱问知识人...
  12. 树莓派 - 蓝牙 (1) 试试Beacon
  13. C#等 句柄是什么?
  14. Linux 冗余网络切换时间,linux下实现双网冗余
  15. 全面设防 让广播风暴远离局域网
  16. 多维泰勒网matlab,非线性定常系统的多维泰勒网优化跟踪控制
  17. 【机器学习实战】构建/绘制决策树(ID3/C4.5)
  18. 【Kaggle】Titanic - Machine Learning from Disaster(二)
  19. 加号和减号在一起怎么读_怎样看化验单上的加号和减号!
  20. ubuntu 18.04 IKFAST 运动学插件生成

热门文章

  1. oracle出现EOF,ora-03113: 通道出现EOF
  2. mysql之join_mysql学习之join用法
  3. 极客大学架构师训练营 微服务架构 领域驱动设计DDD 中台架构、组件设计原则 第十次作业
  4. 用python处理txt文件
  5. MyEclipse问题收集
  6. 深度学习斯坦福cs231n 课程笔记
  7. Affymetrix基因芯片小总结
  8. 编译原理完整学习笔记(一):引论
  9. 【HDU - 4794】Arnold【斐波那契数列循环节】
  10. 【HDU 1024】【线性DP】Max Sum Plus Plus