内容简介:创建SpringBoot项目时,如果不选择starter-web,创建的SpringBoot项目可以正常运行,但运行结束程序便终止了。如果配置starter-web,则正常启动web应用。那么,SpringBoot是如何分辨出来当前应用是为web应用还是其他类型的应用呢?本篇文章带领大家从源码层面进行相应分析。SpringBoot使用枚举类WebApplicationType来定义可支持的应用类型以及相关推断应用类型的常量(数组)及静态方法。下面对该枚举类进行详细的讲解。枚举WebApplicationTy
创建SpringBoot项目时,如果不选择starter-web,创建的SpringBoot项目可以正常运行,但运行结束程序便终止了。如果配置starter-web,则正常启动web应用。那么,SpringBoot是如何分辨出来当前应用是为web应用还是其他类型的应用呢?本篇文章带领大家从源码层面进行相应分析。
枚举WebApplicationType
SpringBoot使用枚举类WebApplicationType来定义可支持的应用类型以及相关推断应用类型的常量(数组)及静态方法。下面对该枚举类进行详细的讲解。
应用类型
枚举WebApplicationType中定义了三个应用类型:
- NONE:应用程序不作为web应用启动,不启动内嵌的服务。
- SERVLET:应用程序以基于servlet的web应用启动,需启动内嵌servlet web服务。
- REACTIVE:应用程序以响应式web应用启动,需启动内嵌的响应式web服务。
推断应用类型
SpringBoot启动时,在创建SpringApplication的构造方法内会调用枚举WebApplicationType的deduceFromClasspath方法获得应用类型并设置当前应用是普通web应用、响应式web应用还是非web应用。
SpringApplication的构造方法中调用并设置源代码:
this.webApplicationType = WebApplicationType.deduceFromClasspath();
deduceFromClasspath方法由枚举WebApplicationType提供,具体实现如下:
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; }
推断的过程中重点调用了ClassUtils.isPresent()方法,用来判断指定类名的类是否存在,是否可以进行加载。ClassUtils.isPresent()方法源代码如下:
public static boolean isPresent(String className, @Nullable ClassLoader classLoader) { try { forName(className, classLoader); return true; }catch (IllegalAccessError err) { throw new IllegalStateException("Readability mismatch in inheritance hierarchy of class [" + className + "]: " + err.getMessage(), err); }catch (Throwable ex) { return false; } }
isPresent()方法调用了forName()方法,如果在调用forName()方法的过程中出现异常则返回false,也就是目标类不存在。否则,返回true。
看一下forName()方法的部分代码:
public static Class<?> forName(String name, @Nullable ClassLoader classLoader) throws ClassNotFoundException, LinkageError { // 此处省略一些非空和基础类型的判断逻辑代码 ClassLoader clToUse = classLoader; if (clToUse == null) { //如果为空则获取默认classLoader clToUse = getDefaultClassLoader(); } try { // 返回加载户的Class。 return Class.forName(name, false, clToUse); } catch (ClassNotFoundException ex) { // 如果直接加载类出现异常,则尝试加载内部类。 int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR); if (lastDotIndex != -1) { // 拼接内部类 String innerClassName = name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1); try { return Class.forName(innerClassName, false, clToUse); } catch (ClassNotFoundException ex2) { // Swallow - let original exception get through } } throw ex; } }
通过以上核心代码,可得知forName()方法主要做的事情就是获得类加载器,尝试直接加载类,如果失败则尝试加载该类的内部类,如果依旧失败,则抛出异常。
因此,整个应用类型的推断分以下步骤:
- SpringBoot调用SpringApplication构造方法;
- SpringApplication构造方法调用枚举类的类型推断方法deduceFromClasspath()。
- deduceFromClasspath()方法通过ClassUtils.isPresent()返回结果为true或false来确定是否加载成功指定的类。
- ClassUtils.isPresent()方法通过调用forName()方法并捕获异常来确定是否能够成功加载该类。
- forName()方法通过尝试加载指定类和指定类的内部类来确定该类是否存在,存在则返回该类,不存在则抛异常。
在类型推断的过程中枚举类WebApplicationType定义了具体去加载哪些类:
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";
- 如果应用程序存在DispatcherHandler并且不存在DispatcherServlet和ServletContainer则为响应式web应用,需加载并启动内嵌的响应式web服务。
- 如果应用程序不包含Servlet和ConfigurableWebApplicationContext则为普通应用程序。
- 其他情况则为基于servlet的web应用,需加载并启动内嵌的web web服务。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于 Java 实现的人脸识别功能(附源码)
- CVPR2019| 南开大学、Facebook等13篇CVPR论文及源码推荐(显著性检测/实例分割/人脸识别/视频动作识...
- 原 荐 Qt封装百度人脸识别+图像识别
- 面部识别软件有助于识别美国内战士兵
- 微软删除人脸识别数据库 源于“伦理”识别
- 文字检测识别系统好用吗?都针对什么进行识别?
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Everything Store
Brad Stone / Little, Brown and Company / 2013-10-22 / USD 28.00
The definitive story of Amazon.com, one of the most successful companies in the world, and of its driven, brilliant founder, Jeff Bezos. Amazon.com started off delivering books through the mail. Bu......一起来看看 《The Everything Store》 这本书的介绍吧!