SpringBoot 启动背后的魔法:SpringApplication 初始化揭秘

举报
bug菌 发表于 2024/11/28 23:22:05 2024/11/28
【摘要】 前言 🚀嘿,亲爱的开发者们,今天咱们要聊的是一个非常关键的 SpringBoot 组件——SpringApplication!想象一下,当你运行一个 SpringBoot 应用时,SpringApplication.run() 就像是启动应用的“发动机”,一旦启动,你的应用就飞速启动,自动配置一切,让你可以专心做自己的业务代码。😎但是,作为一个“后台操作员”,SpringApplica...

前言 🚀

嘿,亲爱的开发者们,今天咱们要聊的是一个非常关键的 SpringBoot 组件——SpringApplication!想象一下,当你运行一个 SpringBoot 应用时,SpringApplication.run() 就像是启动应用的“发动机”,一旦启动,你的应用就飞速启动,自动配置一切,让你可以专心做自己的业务代码。😎

但是,作为一个“后台操作员”,SpringApplication 是如何悄无声息地完成这一切工作的呢?它背后究竟发生了什么?这篇文章,我们就来好好剖析一下 SpringApplication 初始化的整个过程,看看它是如何悄悄为你的应用加油,让你的项目在几秒钟内就能准备好迎接高强度的请求和任务的!🔧

🔧 SpringApplication:启动的“幕后推手”

在 SpringBoot 中,SpringApplication 是应用启动的核心类。它的作用就是帮你启动 Spring 应用上下文,初始化各个组件,甚至帮助你启动一个 Web 服务器。是的,它就是 Spring Boot 启动的“大管家”,你只需要一句话:

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

每次看到这行代码时,我都觉得 SpringBoot 真的是个了不起的工具!💥 只需要一行代码,你就能启动一个功能强大的应用。那么,它到底是怎么工作的呢?今天我们一起探个究竟!

代码解析:

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码展示了一个典型的 Spring Boot 应用的入口类,Application 类的 main 方法用于启动 Spring Boot 应用。以下是代码的详细解析:

  1. Application 类定义
public class Application {
  • Application 是我们定义的类名,通常在 Spring Boot 项目中,它会作为应用的入口类。
  1. main 方法
public static void main(String[] args) {
  • main 方法是 Java 应用程序的入口点。当我们启动 Spring Boot 应用时,main 方法会被 JVM 调用。
  1. SpringApplication.run() 方法
SpringApplication.run(Application.class, args);
  • SpringApplication.run() 是 Spring Boot 提供的一个静态方法,用来启动应用。这个方法会启动 Spring 应用上下文、自动配置并初始化嵌入式 Web 服务器(如 Tomcat、Jetty 或 Undertow)。

  • Application.class 是传递给 run 方法的参数,它指明了应用的主配置类。在 Spring Boot 中,通常这个类使用 @SpringBootApplication 注解,表示这是一个 Spring Boot 应用的配置类。

  • args 是命令行参数,传递给 SpringApplication.run(),这些参数通常可以通过 Spring Boot 的配置文件或命令行中动态修改应用的配置。

@SpringBootApplication 注解

虽然代码片段中没有直接展示 @SpringBootApplication 注解,但通常在实际项目中,Application 类会如下所示:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • @SpringBootApplication 是一个组合注解,它包括了:
    • @EnableAutoConfiguration: 启用 Spring Boot 的自动配置机制。
    • @ComponentScan: 扫描当前包及其子包中的所有 Spring 组件(如 @Component@Service@Repository@Controller 等),自动注入到 Spring 容器中。
    • @Configuration: 标明该类是一个 Spring 配置类。

启动过程

  1. SpringApplication.run(Application.class, args) 被调用时,Spring Boot 会创建一个 ApplicationContext,并开始初始化应用。
  2. 在这个过程中,Spring Boot 会自动加载配置、初始化 beans、启动嵌入式 Web 服务器(如果是 Web 应用)等。
  3. 最终,Spring Boot 应用启动成功,应用开始接受请求(如果是 Web 应用)或者执行其他任务。

🚀 SpringApplication 初始化:一步步带你看

1. 创建 SpringApplication 实例

首先,当你调用 SpringApplication.run() 时,SpringBoot 幕后的魔术师 SpringApplication 类会瞬间被创建并开始初始化。别小看这一行代码,它其实会做很多事情哦!

public static ConfigurableApplicationContext run(Class<?> primarySource, String[] args) {
    SpringApplication application = new SpringApplication(primarySource);
    return application.run(args);
}

SpringApplication 的构造函数接受一个参数,就是你启动的那个类,也就是你传入的 primarySource。这个类通常会被 @SpringBootApplication 注解装饰,SpringBoot 就是通过这个注解来识别你的应用的启动类。

代码解析:

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码展示了 SpringApplication.run() 方法的一个实现。SpringApplication.run() 是 Spring Boot 应用启动的关键方法之一,负责启动整个 Spring 应用上下文。

  1. public static ConfigurableApplicationContext run(Class<?> primarySource, String[] args)

    这是 SpringApplication.run() 方法的声明,返回一个 ConfigurableApplicationContext。这个方法负责启动 Spring Boot 应用并返回 ApplicationContext,即 Spring 容器的上下文。

  2. SpringApplication application = new SpringApplication(primarySource);

    • SpringApplication 是 Spring Boot 的核心类,负责启动和配置 Spring 应用。
    • primarySource 参数是应用的主配置类,通常是带有 @SpringBootApplication 注解的类。这个类作为应用的入口,Spring Boot 会基于这个类来配置和启动应用。

    通过传入 primarySource,Spring Boot 知道从哪里开始扫描和配置 Spring 容器。它会扫描 primarySource 类所在的包及其子包,加载其中的所有组件。

  3. return application.run(args);

    • run() 方法启动应用并返回一个 ConfigurableApplicationContext。这是 Spring 容器的实例,可以用来管理应用中的所有 beans 和其他组件。
    • args 参数是命令行参数,可以用来传递给应用来修改应用的行为。Spring Boot 会解析这些参数,并在应用启动时根据这些参数配置相应的内容。

详细解释

  • ConfigurableApplicationContext 是 Spring 应用上下文的一个接口,提供了对 Spring 容器的配置、刷新和关闭等操作的支持。它是 ApplicationContext 的一个扩展,Spring Boot 中的应用上下文通常是 AnnotationConfigApplicationContextGenericWebApplicationContext 的实例,具体取决于应用是否是 Web 应用。

  • SpringApplication 是 Spring Boot 中用于启动应用的核心类。它的职责不仅仅是启动 Spring 应用上下文,还包括:

    • 自动配置 Spring 应用
    • 设置和管理应用的环境配置(如 application.propertiesapplication.yml
    • 启动嵌入式 Web 服务器(如 Tomcat、Jetty 或 Undertow,取决于应用类型)

启动流程

  1. 当调用 SpringApplication.run() 时,SpringApplication 会根据传入的主配置类(primarySource)扫描相关的类和组件。
  2. 它会自动加载配置文件(如 application.propertiesapplication.yml),并使用它们来配置 Spring 容器。
  3. 如果是 Web 应用,Spring Boot 会自动启动一个嵌入式 Web 服务器(如 Tomcat),并开始监听请求。
  4. 最终,Spring Boot 应用的上下文被创建和初始化,应用进入运行状态。

2. 准备环境配置

接下来,SpringApplication 会开始准备应用的环境配置。这是 SpringBoot 启动的第一步工作。它会通过配置文件(如 application.propertiesapplication.yml)来确定当前应用所处的环境,例如是开发环境、测试环境还是生产环境。

this.environment = prepareEnvironment(listeners, args);

这段代码看似简单,但它背后做了很多准备工作,包括加载各种配置文件,确定要使用的配置源,以及处理命令行参数等。SpringBoot 这么“贴心”,连环境都帮你准备好了!👏

3. 加载应用上下文

接下来,SpringApplication 进入最重要的一个环节——加载应用上下文(ApplicationContext)。这时,它会初始化 Spring 容器,开始创建和管理应用所需要的 Bean。

ConfigurableApplicationContext context = createApplicationContext();

在这个阶段,SpringApplication 会根据应用类型(Web 或非 Web)来决定加载哪种类型的 ApplicationContext。如果是 Web 项目,它会创建一个支持 Web 环境的 AnnotationConfigServletWebApplicationContext,如果是非 Web 项目,它会创建一个普通的 AnnotationConfigApplicationContext

4. 启动 Web 服务器(Web 项目特有)

如果你正在开发的是一个 Web 应用程序,那么 SpringApplication 会为你启动一个内嵌的 Web 服务器。常见的 Web 服务器包括 Tomcat、Jetty 和 Undertow 等。SpringBoot 的伟大之处在于,它帮你自动配置好 Web 服务器,免去了手动配置的繁琐。

if (this.webApplicationType == WebApplicationType.SERVLET) {
    this.webServer = new TomcatWebServer(this.webApplicationType);
}

这意味着你只需要专注于业务代码,而 SpringBoot 会在后台默默启动一个 Tomcat,确保你的 Web 应用能够正常运行。简直太贴心了!🎉

代码解析:

在本次的代码演示中,我将会深入剖析每句代码,详细阐述其背后的设计思想和实现逻辑。通过这样的讲解方式,我希望能够引导同学们逐步构建起对代码的深刻理解。我会先从代码的结构开始,逐步拆解每个模块的功能和作用,并指出关键的代码段,并解释它们是如何协同运行的。通过这样的讲解和实践相结合的方式,我相信每位同学都能够对代码有更深入的理解,并能够早日将其掌握,应用到自己的学习和工作中。

这段代码展示了 Spring Boot 应用如何根据应用类型来初始化嵌入式 Web 服务器。在这个示例中,TomcatWebServer 是 Spring Boot 用于支持 Servlet Web 应用的嵌入式 Tomcat 服务器的实现。

if (this.webApplicationType == WebApplicationType.SERVLET) {
    this.webServer = new TomcatWebServer(this.webApplicationType);
}
  1. this.webApplicationType == WebApplicationType.SERVLET

    • 这一行检查 webApplicationType 的值,是否等于 WebApplicationType.SERVLET

    • WebApplicationType 是一个枚举类,它定义了 Web 应用的类型。它通常有以下几种值:

      • SERVLET:表示一个传统的基于 Servlet 的 Web 应用。Spring Boot 会使用嵌入式的 Servlet 容器(例如 Tomcat、Jetty 或 Undertow)来启动应用。
      • REACTIVE:表示一个反应式的 Web 应用,通常使用反应式 Web 框架(例如 WebFlux)以及支持异步、非阻塞的服务器。
      • NONE:表示没有 Web 服务器,即该应用不是 Web 应用,或者它仅用于批处理任务、命令行应用等。
    • 在这里,如果应用类型是 SERVLET,则表示该应用是一个传统的 Web 应用(基于 Servlet 技术的应用),需要使用一个传统的 Servlet 容器(如 Tomcat)来运行。

  2. this.webServer = new TomcatWebServer(this.webApplicationType);

    • 如果应用类型为 SERVLET,那么 Spring Boot 会创建一个 TomcatWebServer 实例。
    • TomcatWebServer 是 Spring Boot 用于运行 Servlet 应用的嵌入式 Tomcat 实现。它会负责启动 Tomcat 服务器,并将 Spring 应用与 Tomcat 容器集成。
    • this.webApplicationType 被传递给 TomcatWebServer 构造函数,表示应用的类型。这对于某些配置可能是有意义的,比如确定是否使用特定的 Tomcat 配置选项,或者是否启用某些容器功能。

背后原理

Spring Boot 提供了三种类型的嵌入式 Web 服务器支持:

  • Tomcat(默认)
  • Jetty
  • Undertow

SpringApplication 会根据应用的配置来选择适当的 Web 服务器。例如:

  • 如果应用是一个传统的 Servlet Web 应用(WebApplicationType.SERVLET),那么 Spring Boot 会使用嵌入式的 Tomcat(或 Jetty、Undertow,如果配置了其他服务器)来启动应用。
  • 如果是反应式 Web 应用(WebApplicationType.REACTIVE),Spring Boot 会使用适合反应式应用的服务器(例如 Netty)。

在默认配置下,Spring Boot 会自动选择 Tomcat 作为嵌入式 Web 服务器。如果需要,您可以通过配置文件或依赖管理来更改 Web 服务器的类型。

示例应用类型

  • Servlet 应用(WebApplicationType.SERVLET

    • 使用传统的基于 Servlet 的 Web 应用结构,适用于 Spring MVC 或其他 Servlet 技术。
    • 默认情况下,Spring Boot 会使用嵌入式 Tomcat 作为 Web 服务器。
  • 反应式应用(WebApplicationType.REACTIVE

    • 使用响应式 Web 架构(如 Spring WebFlux)来处理异步、非阻塞请求。
    • 默认情况下,Spring Boot 会使用嵌入式 Netty 作为 Web 服务器,适合反应式编程模型。
  • 非 Web 应用(WebApplicationType.NONE

    • 不是 Web 应用,Spring Boot 不会启动嵌入式 Web 服务器。

5. 初始化监听器和初始化器

启动过程中,SpringApplication 会加载和触发多个监听器和初始化器。监听器用于监听各种应用事件,而初始化器则可以用来在应用启动之前,做一些额外的工作,例如修改 Spring 环境或调整上下文。

callRunnerBeans(context, args);

这里 callRunnerBeans() 方法会执行实现了 CommandLineRunnerApplicationRunner 接口的 Runner,这些 Runner 通常会在应用启动后,执行一些初始化任务或其他自定义操作。

6. 完成初始化,应用就绪

最终,当所有的环境、上下文、服务器、监听器都准备好后,SpringBoot 应用就可以正常启动并提供服务了。此时,你的应用已经处于“待命”状态,随时准备好接受请求,服务你的用户!

🧳 总结:SpringApplication,自动化的艺术

今天的文章,我们从源码层面解析了 SpringBoot 启动时 SpringApplication 的初始化过程。可以看到,SpringApplication 就像是一个神奇的“启动引擎”,它在背后默默做了很多准备工作。你只需要通过 SpringApplication.run() 启动应用,它就会自动帮你配置好所有环境、加载应用上下文、启动 Web 服务器,甚至触发监听器。

SpringBoot 的强大之处就在于它极大地简化了配置,让开发者可以专注于业务开发,而不需要担心底层的繁琐配置。这就是为什么 SpringBoot 成为当今最受欢迎的开发框架之一的原因。🚀

希望今天的解析对你了解 SpringApplication 初始化过程有所帮助!当然,如果你对 SpringBoot 源码有更多兴趣,随时欢迎来一起探讨哦!🤗

🧧福利赠与你🧧

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学SpringBoot」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门SpringBoot,就像滚雪球一样,越滚越大, 无边无际,指数级提升。

最后,如果这篇文章对你有所帮助,帮忙给作者来个一键三连,关注、点赞、收藏,您的支持就是我坚持写作最大的动力。

同时欢迎大家关注公众号:「猿圈奇妙屋」 ,以便学习更多同类型的技术文章,免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板、技术文章Markdown文档等海量资料。

✨️ Who am I?

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,掘金等各大社区平台签约作者,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 30w+;更多精彩福利点击这里;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。

-End-

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。