main run方法没用_Spring Application实例化流程和构造方法参数

SpringBoot构造流程源码分析

Spring Boot 的启动非常简单,只需执行一-个简单的 main 方法即可,但在整个 main 方法中,Spring Boot 都做了些什么呢?本章会为大家详细讲解 Spring Boot 启动过程中所涉及的源代码和相关知识点。只有了解 Spring Boot 启动时都做了些什么,我们在实践过程中才能更好地运用 Spring Boot,更好地排查问题,并借鉴 Spring Boot 的设计理念进行创新。

我们再来看一下 Spring Boot 的启动入口类源代码。

@SpringBootApplicationpublic class SpringLearnApplication {public static void main(String[] args) {SpringApplication. run(SpringLearnApplication. class, args);}}

在上一章中,我们通过入口类的@SpringBootApplication 注解展开讲解 了SpringBoot的核 心 机 制 。 而 本 章 则 围 绕 SpringApplication 类 的 静 态 方 法 一 run 方 法 的 初 始 化 类SpringApplication 自身的功能进行讲解。

7920732f0a27579f930a033bbcd7d0e7.png

SpringApplication的初始化简介

在入口类中主要通过 SpringApplication 的静态方法一-run 方 法进行 SpringApplication类的实例化操作,然后再针对实例化对象调用另外-个 run 方法来完成整个项目的初始化和启动。本章重点围绕此过程的前半部部分(即 SpringApplication 类的实例化)来讲解。

public class SpringApplication {public static ConfigurableApplicationContext run(Class> primarySource,return run(new Class>[] { primarySource }, args);public static ConfigurableApplicat ionContext run(Class>[] primarySourceString[] args) {//创建 SpringApplication 对象并执行其 run 方法return new SpringApplication(primarySources). run(args);}}

通过入口类的方法进入,可以看到 SpringApplication 的实例化只是在它提供的静态 run 方法中新建了一个 SpringApplication 对象。其中参数 primarySources 为加载的主要资源类,通常就是 Spring Boot 的入口类,args 为传递给应用程序的参数信息。

借鉴 SpringApplication 内部 run 方法的实现,我们也可以直接新建一个 SpringApplication对象,并调用其 run 方法。因此,启动程序也可以如此来写:

@SpringBootApplicationpublic class Springl earnApplication {public static void main(String[] args)new SpringApplication(SpringL earnApplication.class).run(args); }}

这样写程序的一个好处便是,可以通过 SpringApplication 提供的一 -些方法(setXX 或addXX 方法)来进行指定功能的定制化设置。

下面将重点围绕 SpringApplication 类的实例化展开。

21bf257fec52f173d0e15400cfc3af37.png

SpringApplication 实例化流程

上面我们了解了进行 SpringApplication 实例化的基本方法,下面我们先通过一-张简单的流程图来系统地学习在创建 SpringApplication 对象时都进行了哪些核心操作,如图 3-1 所示。

a30a1674b9e088989214141e3c8fa696.png

通过图 3-1 可以看出,在 SpringApplication 对象实例化的过程中主要做了 3 件事:参数赋值给成员变量、应用类型及方法推断和 ApplicationContext 相关内容加载及实例化。

我们结合流程图看一下 SpringApplication 两个构造方法的核心源代码。

public SpringApplication(Class>... primarySources) {this(nu1l, primarySources);@SuppressWarnings({ "unchecked", "rawtypes" })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 应用类型this . webApplicationType = WebApplicationType. deduceF romClasspath();//加戴并初始化 Appl icationContextInitial izer 及相关实现类setInitializers((Collection)getSpringFactoriesInstances (ApplicationContextInitializer.class));//加戴并初始化 Appl icationL istener 及相关实现类setListeners((Collection) getSpringFactoriesInstances (ApplicationListener.class));//推断 main 方法 Class 类this . mainApplicationClass = deduceMainApplicationClass();}

SpringApplication 提供了两个构造方法,核心业务逻辑在第二个构造方法中实现,在后面章节我们会从构造方法中的具体实现入手进行详细讲解,先来了解 SpringApplication 的初始化过程。

SpringApplication 构造方法参数

SpringApplication 的核心构造方法有两个参数,第一个为 ResourceLoader resourcel oader,第二个 为 Class...primarySources.

ResourceLoader 为资源加载的接口,在 Spring Boot 启动时打印对应的 banner 信息,默认采用的就是 DefaultResourceLoader。 实战过程中,如果程序未按照 Spring Boot 的“约定”将 banner 的内容放置于 classpath 下,或者文件名不是 banner.*格式,默认资源加载器是无法加载到对应的 banner 信息的,此时可通过 ResourceL oader 来指定需要加载的文件路径。

第二个参数 Class>.. .primarySources,为可变参数,默认传入 SpringBoot 入口类。如果作 为 项 目 的 引 导 类 , 此 参 数 传 入 的 类 需 要 满 足 一 个 条 件 , 就 是 被 注 解@EnableAutoConfiguration 或其组合注解标注。由于@SpringBootApplication 注解中包含了@EnableAutoConfiguration 注解,因此被@SpringBootApplication 注解标注的类也可作为参数传入。当然,该参数也可传入其他普通类。但只有传入被@EnableAutoConfiguration标注的类才能够开启 Spring Boot 的自动配置。

下面我们以实例来演示以其他引导类为入口类进行的 Spring Boot 项目启动。先在入口类同级创建一个 OtherApplication 类, 使用@SpringBootApplication 进行注解。

@SpringBootApplicationpublic class OtherApplication {}

然后在原来的入口类 SpringL earnApplication 的 main 方法中将 primarySources 参数的值由 SpringL earnApplication.class 替 换 为 OtherApplication.class, 并 将 SpringLearnApplication 类上的注解去掉。

public class SpringLearnApplication {public static void main(String[] args) {new SpringApplication(OtherApplication. class). run(args);}

执行 main 方法,程序依旧可完成自动配置,可以正常访问。因此,决定 Spring Boot 启动的入口类并不一定是 main 方法所在类,而是直接或间接被@EnableAutoConfiguration 标注的类。在此也证明了之前提到的@SpringBootApplication 和@EnableAutoConfiguration 入口并没有依赖关系,只是无论通过 new 创建 SpringApplication 对象再调用 run 方法或是通过 SpringApplication 的 run 方法来启动程序,都不离不开 primarySources 参数。

同时,在 SpringApplication 类中还提供 了追加 primarySources 的方法,代码如下。

public void addPrimarySources (Collection> additionalPrimarySources) {this . primarySources . addAll( additionalPrimarySources );}

回 到 primarySources 参 数 中 , 在 实 例 化 SpringApplication 类 过 程 中 并 没 有 对primarySources 参数做过多处理,只是将其转化为 Set 集合,并赋值给 SpringApplication的私有成员变量 Set> primarySources,代码如下。

public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {this. primarySources = new LinkedHashSet<> (Arrays . aslist (primarySources));}

注意 SpringApplication 的私有变量 primarySources 依旧为 LinkedHashSet,它具有去重的特性。

至此,SpringApplication 构造时参 数赋值对应变量这一步便完成了 。

本文给大家讲解的内容是SpringApplication初始化简介、实例化流程和构造方法参数

  1. 下篇文章给大家讲解的是Web应用类型推断和ApplicationContextlnitializer加载;
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值