SpringBoot源码之deduceFromClasspath方法推断应用程序类型原理

在SpringBoot中,SpringBoot对应用程序进行了3种类型的区分,使用了一个枚举类WebApplicationType,而deduceFromClasspath方法就在这个枚举类中。

WebApplicationType的值有以下3个

/**
 * The application should not run as a web application and should not start an
 * embedded web server.
 */
NONE,

/**
 * The application should run as a servlet-based web application and should start an
 * embedded servlet web server.
 */
SERVLET,

/**
 * The application should run as a reactive web application and should start an
 * embedded reactive web server.
 */
REACTIVE;

具体的区别可以阅读注释,英语不好的我做个简单解释:

NONE就是什么都没有,按照正常的代码走即可不需要额外启动web容器如tomcat等;SERVLET则代表这是一个传统的servlet的web程序,对应SpringMVC,表示需要启动对应的web容器支持如tomcat等;REACTIVE则是一种比较新的非阻塞的web框架,对应spring-webflux,需要启动支持reactive的web容器,这里我对webflux不太熟悉不过多解释。

deduceFromClasspath方法的源码如下:

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()这个方法,通过这个方法来判断常量中的类是否存在。该方法的最终实现原理是通过Class.forName尝试加载某个类,如果能够成功加载,则证明这个类存在,反之发生异常则代表类不存在。

所以deduceFromClasspath方法的实现原理也很好理解,通过判断webflux相关的类是否存在,存在则认为是REACTIVE类型,不存在继续判断servlet相关的类是否存在,都存在则认为是SERVLET类型,都不存在则认为是NONE类型。具体的类的类型可以直接查看源码,不过多赘述。