SpringBoot构造流程源码分析:Web应用类型推断
Web应用类型推断完成变量赋值之后 , 在 SpringApplication 的构造方法中便调用了 WebApplication Type 的deduceFromClasspath 方法来进行 Web 应用类型的推断 。 SpringApplication 构造方法中的相关代码如下 。
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {this . webApplicationType = WebApplicat ionType . deduceFromClasspath();}
该行代码调用了 WebApplicationType 的 deduceFromClasspath 方法 , 并将获得的 Web 应用类型赋值给私有成员变量 webApplicationType.
WebApplicationType 为枚举类 ,它定义了可能的 Web 应用类型 , 该枚举类提供了三类定义:枚举类型、推断类型的方法和用于推断的常量 。 枚举类型包括非 Web 应用、基于 SERVLET 的 Web 应用和基于 REACTIVE 的 Web 应用 , 代码如下 。
public enum WebApplicationType {//非 web 应用类型NONE,//基于 SERVLET 的 Web 应用类 型SERVLET ,//基 FREACTIVE 的 eb 应用类型REACTIVE;}
WebApplicationType 内针对 Web 应用类型提供了两个推断方法:
deduceFromClasspath 方法和 deduceFromApplicationContext 方法 。 在此我们使用了deduceFromClasspath 方法 , 下面重 点分析该方法的实现 。
public enum WebApplicationType {..private static final String[] SERVLET_ INDICATOR_ CLASSES = { "javax. servlet . Servlet","org. springframework . web . context . ConfigurableWebApplicationContext" }private static final String WEBMVC_ INDICATOR_ CLASS = "org. springframewor+ "web. servlet . DispatcherServlet";private static final String WEBFLUX_ INDICATOR_ _CLASS = "org.'+ "springframework. web. reactive . DispatcherHandler";private static final String JERSEY INDICATOR_ CLASS = "org. glassfish.jerseyservlet. ServletContainer";//基于 classpath 的 web 应用类型推断 , 核心实现方法为 ClassUtils. isPresentstatic WebApplicationType deduceF romClasspath() {if (ClassUtils. isPresent (WEBFLUX_ INDICATOR_ CLASS, null)for (String className : SERVLET_ INDICATOR_ CLASSES) {if (!ClassUtils. isPresent(className, nul1)) {return WebApplicationType . NONE;return WebApplicationType . SERVLET;}
方法 deduceFromClasspath 是基于 classpath 中类是否存在来进行类型推断的 , 就是判断指定的类是否存在于 classpath 下 ,并根据判断的结果来进行组合推断该应用属于什么类型 。 deduceFromClasspath 在判断的过程中用到了 ClassUtils 的 isPresent 方法 。 isPresent方法的核心机制就是通过反射创建指定的类 , 根据在创建过程中是否抛出异常来判断该类是通过上面的源代码 , 我们可以看到 deduceFromClasspath 的推断逻辑如下 。
.当 DispatcherHandler 存在 , 并且 DispatcherServlet 和 ServletContainer 都不存在 , 则返回类型为 WebApplicationType.REACTIVE.
【SpringBoot构造流程源码分析:Web应用类型推断】.当 SERVLET 或 ConfigurableWebApplicationContext 任何一个不存在时 , 说明当前应用为非 Web 应用 , 返回 WebApplicationType NONE 。
当应用不为 REACTIVE Web 应用 , 并且 SERVLET 和 ConfigurableWebApplicationContext都存在的情况下 , 则为 SERVLET 的 Web 应用 , 返回 WebApplicationType .SERVLET.
文章插图
ApplicationContextlnitializer加载源码解析
ApplicationContextlnitializer是SpringIOC 容器提供的一个接口 , 它是一个回调接口 , 主要目的是允许用户在 ConfigurableApplicationContext 类型(或其子类型)的 ApplicationContext做 refresh 方法调用刷新之前 , 对 ConfigurableApplicationContext 实例做进一步的设 置或处理 。 通常用于应用程序上下文进行编程初始化的 Web 应用程序中 。
ApplicationContextlnitializer 接口只定义了一-个 initialize 方法 , 代码如下 。 public interface ApplicationContextInitializer
ApplicationContextlnitializer 接口的 initialize 方法主要是为了初始化指定的应用上下文 。 而对应的上下文由参数传入 , 参数为 ConfigurableApplicationContext 的子类 。
在完成了 Web 应用类型推断之后 , ApplicationContextlnitializer 便开始进行加载工作 , 该过程可分两步骤:获得相关实例和设置实例 。 对应的方法分别为 getSpringFactoriesInstances和 setlnitializers 。
SpringApplication 中获得实例相关方法代码如下 。
privateCollection getSpringF actoriesInstances(Class type) {return getSpringFactoriesInstances(type, new Class>[] {});privateCollection getSpringF actoriesInstances(Class type,Class>[] parameterTypes, object... args) {ClassLoader classLoader = getClassLoader();//加载对应配置 , 这里采用 LinkedHashSet 和名称来确保加载的唯一 性Set names = new LinkedHashSet<> (SpringF actoriesLoader . loadF actoryNames (type, classLoader));//创建实例List instances = createSpringFactoriesInstances (type,parameterTypeS,classLoader, args, names);//排序操作AnnotationAwareOrderComparator . sort(instances);return instances;}
- 页面|如何简单、快速制作流程图?上班族的画图技巧get
- 精英|业务流程图怎么绘制?销售精英的经验之谈
- 页面|流程图怎样画?老板要我帮他做个组织结构图
- |苹果iphone12怎么退货 iphone12退货政策流程条件攻略
- SpringBoot+MyBatis+MySQL读写分离实现
- 禁止拷贝构造,禁止bug
- 搭建私有Sentry日志收集系统并集成到springboot
- 工业机械手臂外部模式使用流程及注意事项
- 构造流程源码分析:ApplicationListener加载
- 营销|商业综合体开发营销全流程图