购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 SpringApplication构造方法分析

在run方法中可以看到它进行了SpringApplication的构造,对于SpringApplication的构造函数的分析十分重要。本节将对SpringApplication构造方法进行分析,具体的构造函数代码如下:

在SpringApplication的构造方法中主要的处理流程如下:

(1)设置资源加载器;

(2)设置主要启动类;

(3)设置Web应用类型标记;

(4)获取BootstrapRegistryInitializer集合并设置给成员变量bootstrapRegistryInitializers;

(5)获取ApplicationContextInitializer集合并设置给成员变量initializers;

(6)获取ApplicationListener集合并设置给成员变量listeners;

(7)设置应用类。

在启动SampleWebStaticApplication时通过构造函数创建的SpringApplication成员变量的数据信息如图2-1所示。

在构造函数中会对成员变量initializers进行初始化,在本例中初始化的成员变量initializers的具体数据表如图2-2所示。

在构造函数中还对成员变量listeners进行了初始化,在本例中成员变量listeners的数据信息如图2-3所示。

图2-1 SpringApplication成员变量的数据信息

图2-2 initializers的具体数据表

图2-3 listeners的数据信息

在SpringApplication的构造方法中引用了4个方法,接下来对这4个方法进行分析:

(1)WebApplicationType.deduceFromClasspath方法用于确定Web应用类型标记;

(2)getBootstrapRegistryInitializersFromSpringFactories方法用于获取BootstrapRegistryInitializer集合;

(3)getSpringFactoriesInstances方法用于获取Spring工厂实例;

(4)deduceMainApplicationClass方法用于推到核心应用类。

2.2.1 WebApplicationType.deduceFromClasspath方法分析

本节将对WebApplicationType.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;
}

在deduceFromClasspath方法中会得到Web应用的类型,在这个处理过程中包含3种类型:

(1)响应式REACTIVE;

(2)非Web应用;

(3)Servlet应用。

在该方法中主要的判断依据是ClassUtils.isPresent方法,isPersent方法调用还需要依靠以下4个成员变量:

(1)WEBFLUX_INDICATOR_CLASS;

(2)WEBMVC_INDICATOR_CLASS;

(3)JERSEY_INDICATOR_CLASS;

(4)SERVLET_INDICATOR_CLASSES。

2.2.2 getBootstrapRegistryInitializersFromSpringFactories方法分析

本节将对getBootstrapRegistryInitializersFromSpringFactories方法进行分析,该方法主要用于获取Bootstrapper和BootstrapRegistryInitializer相关的工厂接口,具体处理代码如下:

在getBootstrapRegistryInitializersFromSpringFactories方法中的处理流程如下:

(1)通过getSpringFactoriesInstances方法将Bootstrapper类型对应的工厂检索到;

(2)将检索到的Bootstrapper类型的工厂遍历调用initialize方法后放入返回集合中;

(3)通过getSpringFactoriesInstances方法将BootstrapRegistryInitializer类型的工厂寻找出来放入返回集合中;

(4)返回结果集合。

2.2.3 getSpringFactoriesInstances方法分析

本节将对getSpringFactoriesInstances方法进行分析,该方法用于搜索工厂接口,具体处理代码如下:

在上述代码中主要的处理流程如下:

(1)获取类加载器;

(2)获取类型对应的名称集合,这部分数据在META-INF/spring.factories文件中;

(3)通过名称、类型和参数等进行实例化;

(4)将实例化结果进行排序后返回,排序需要依赖Order相关内容。

2.2.4 createSpringFactoriesInstances方法分析

本节将对createSpringFactoriesInstances方法进行分析,具体处理代码如下:

createSpringFactoriesInstances方法主要目的是将方法参数names进行实例化,具体实例化步骤如下:

(1)通过类加载器根据参数names中的元素获取类对象;

(2)通过第(1)步中获取的类对象进一步获取构造函数对象;

(3)通过BeanUtils进行实例化;

(4)放入数据集合(变量instances)。

2.2.5 deduceMainApplicationClass方法分析

本节将对deduceMainApplicationClass方法进行分析,该方法用于确认主类,具体处理代码如下:

private Class<?> deduceMainApplicationClass() {
   try {
      // 提取当前堆栈
      StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
      for (StackTraceElement stackTraceElement :stackTrace) {
          // 找到main函数所在的类
          if ("main".equals(stackTraceElement.getMethodName())) {
             return Class.forName(stackTraceElement.getClassName());
          }
      }
   }
   catch (ClassNotFoundException ex) {}
   return null;
}

在deduceMainApplicationClass方法中主要的处理流程如下:

(1)获取当前调用堆栈;

(2)遍历当前堆栈集合,如果方法名称是main则会作为最终返回结果。

至此,对于SpringApplication的构造方法分析就告一段落,下一节将开始着重分析run方法。 5f6/+1mn2RDpqBiX8B/xKStiwYwuuVvyHLVFkApfKCM9tsD9WNmvF3+ZA+rAWQ94

点击中间区域
呼出菜单
上一章
目录
下一章
×