SpringBoot的应用类型识别机制

一、SpringBoot  应用类型:

应用类型

 

关键类

加载服务器

备注

Web应用

响应式web应用(webflux)

 

web.reactive.DispatcherHandler

 

加载启动内嵌的响应式web服务器

 

Servlet Web应用

web.servlet.DispatcherServlet

javax.servlet.Servlet

 

加载启动内嵌的web服务器

(如Tomcat)

 

普通应用

java进程

 

普通java进程

 


二、推断应用的类型:

SpringBoot启动时,在创建SpringApplication对象时,会自动去识别并设置当前应用是普通web应用、响应式web应用还是非web应用。通过以下二程方式:判断应用类型。

public enum WebApplicationType {

   /**
    * 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 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;

   /**
    * 1.通过ClassLoader查找该虚拟机jvm所加载的类中有没有特定的类。
    * 2.特定的类:pom文件声明不同的依赖包(jar)里存在。
    * 
    */
   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;
    
  }

 

  • 1、如果应用程序中存在org.springframework.web.reactive.DispatcherHandler这个类,则表示是一个响应式web应用,项目在启动时,需要去加载启动内嵌的响应式web服务器。

  • 2、如果应用程序中既不存在javax.servlet.Servlet类,也不存在org.springframework.web.context.ConfigurableWebApplicationContext这个类,则表示当前应用不是一个web应用,启动时无需加载启动内嵌的web服务器。

  • 3、除上述两种情况外,则表示当前应用是一个servlet的web应用,启动时需要加载启动内嵌的servlet的web服务器(比如Tomcat)。

三、推断并设置main方法的定义类(启动入口类)

SpringBoot是通过获取当前方法的调用栈信息,来判断当前main函数所在的类。找到入口函数。

public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
  //推断应用的类型:主要是判断是普通web应用、响应式web应用、非web应用
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
  //查找并加载所有可用的ApplicationContextInitializer
   setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
   //查找并加载所有可用的ApplicationListener
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //推断并设置main方法的定义类(启动类)
    this.mainApplicationClass = deduceMainApplicationClass();
}

/**
* 定义的类(包含main()方法),如myApplication.java, 
* 1. myApplication.java本身也是一个普通@Configution类,需要加载类里的@Bean注入IOC容器
* 2. myApplication.java 默认情况下的扫描package是以myApplication.java所在的包。
*/
private Class deduceMainApplicationClass() {
   try {
      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
      for (StackTraceElement stackTraceElement : stackTrace) {
         if ("main".equals(stackTraceElement.getMethodName())) {
            return Class.forName(stackTraceElement.getClassName());
         }
      }
   }
   catch (ClassNotFoundException ex) {
      // Swallow and continue
   }
   return null;
}

 

你可能感兴趣的:(SpringBoot的应用类型识别机制)