SpringBoot启动流程SpringApplication准备阶段源码分析

下面就详细讲解一下“SpringBoot启动流程SpringApplication准备阶段源码分析”的完整攻略。SpringBoot启动流程可以分为准备阶段、运行阶段、关闭阶段三个阶段,而本篇主要介绍SpringApplication的准备阶段。

SpringBoot启动流程简介

SpringBoot启动流程包括如下三个阶段:

  1. 准备阶段:包括ApplicationContext的初始化、Environment的初始化等。
  2. 运行阶段:包括@Configuration、@SpringBootApplication加载实例化、自定义监听器的加载、加载web容器等。
  3. 关闭阶段:容器的销毁、自定义销毁器的调用等。

在三个阶段中,准备阶段是SpringBoot启动的基础。其中,SpringApplication负责整个启动流程的控制。

SpringApplication准备阶段源码分析

1. run方法

SpringApplication的主要方法是run方法。当我们在Main方法中启动SpringBoot时,SpringApplication的run方法会被执行。

在这个方法中,SpringApplication会先创建一个SpringApplicationRunListeners对象,并调用它的starting方法。

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        configureIgnoreBeanInfo(environment);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[] { ConfigurableApplicationContext.class }, context);
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        listeners.started(context);
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        listeners.running(context);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    return context;
}

2. prepareEnvironment方法

prepareEnvironment方法是准备环境变量的过程,即将ConfigurableEnvironment对象的属性设置好,后续创建IOC容器和相关环境时需要用到。

private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
        ApplicationArguments applicationArguments) {
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    listeners.environmentPrepared(environment);
    if (this.addConversionService) {
        ConversionService conversionService = ApplicationConversionService.getSharedInstance();
        environment.setConversionService((ConfigurableConversionService) conversionService);
    }
    configurePropertySources(environment, applicationArguments.getSourceArgs());
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    return environment;
}

在这个方法中,首先使用getOrCreateEnvironment方法,获取或者创建ConfigurableEnvironment对象。然后通过方法configureEnvironment和configurePropertySources对ConfigurableEnvironment进行初始化。这些方法里面设置了一些常用的环境配置,比如设置环境的名称、激活的profiles、加载配置文件等等。最后,SpringApplication会将ConfigurableEnvironment转换成Environment对象,将其放到Environment中,以备后续使用。

3. configureHeadlessProperty方法

configureHeadlessProperty方法用于设置系统参数java.awt.headless的值,默认值为:System.getProperty("java.awt.headless", Boolean.FALSE.toString())。

private void configureHeadlessProperty() {
    System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless));
}

4. configureIgnoreBeanInfo方法

configureIgnoreBeanInfo方法设置了系统参数spring.beaninfo.ignore的值,用于禁止Spring加载一些bean信息,加快Spring启动速度。

private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
    if (this.beanInfoFactories.isEmpty()) {
        System.setProperty("spring.beaninfo.ignore", "true");
    }
    else {
        for (BeanInfoFactory beanInfoFactory : this.beanInfoFactories) {
            BeanInfoUtils.registerBeanInfo(beanInfoFactory);
        }
    }
}

5. getRunListeners方法

getRunListeners方法是获取SpringApplicationRunListeners对象的方法,这里会通过Spring Factories的方式,获取所有SpringApplicationRunListener的实现。

private SpringApplicationRunListeners getRunListeners(String[] args) {
    Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
    return new SpringApplicationRunListeners(logger,
            getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}

之后,SpringApplication会先调用SpringApplicationRunListeners的starting方法,并执行所有SpringApplicationRunListener的starting方法。

public void starting() {
    for (SpringApplicationRunListener listener : this.listeners) {
        listener.starting();
    }
}

至此,SpringApplication的准备阶段就已经完成了。接下来就是SpringApplication的运行阶段和关闭阶段。在这个过程中,SpringApplication会初始化Springboot的配置,并在ApplicationContext中启动所有的bean,为我们提供便捷的web服务。

代码示例1:SpringApplication的基本使用

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

代码示例2:多环境配置SpringApplication的使用

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Application.class);
        app.setDefaultProperties(Collections.singletonMap("server.port", "8083"));
        app.run(args);
    }
}

以上简要地介绍了SpringBoot启动流程SpringApplication的准备阶段源码分析以及两个代码示例。希望对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot启动流程SpringApplication准备阶段源码分析 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • springboot+mybatis通过实体类自动生成数据库表的方法

    下面我将详细讲解“springboot+mybatis通过实体类自动生成数据库表的方法”的完整攻略,其中会包含两个示例。 1. 引入依赖 首先,在工程的pom.xml文件中引入如下依赖: <!– Spring Boot 依赖 –> <dependency> <groupId>org.springframework.bo…

    Java 2023年5月20日
    00
  • SpringAop日志找不到方法的处理

    在使用Spring AOP时,有时会出现日志找不到方法的情况。这通常是由于切点表达式不正确或目标方法的访问修饰符不正确导致的。在本文中,我们将提供一个完整的攻略,以解决Spring AOP日志找不到方法的问题,并提供两个示例说明。 1. 确认切点表达式 在使用Spring AOP时,我们需要使用切点表达式来指定要拦截的方法。如果切点表达式不正确,则可能会导致…

    Java 2023年5月18日
    00
  • Java8如何基于flatMap处理异常函数

    Java 8中的flatMap函数提供了一种优雅的处理异常函数的方法,使得我们可以更容易地在代码中处理异常。下面是一些基于flatMap的处理异常函数的可行方法和示例: 1. 使用Optional和flatMap Optional是Java 8中的一个类,它可以处理可能为空的对象。我们可以在函数中返回一个Optional对象,然后使用flatMap来处理异常…

    Java 2023年5月27日
    00
  • Java中的异常处理如何提高程序安全性?

    Java中的异常处理机制是提高程序安全性和稳定性的重要手段之一。它可以让我们在程序运行时捕获和处理可能发生的异常情况,以避免程序的崩溃或者无效输出。 以下是使用Java中的异常处理机制来提高程序安全性的一些攻略: 异常分类 在Java中异常是分为可检查异常和非可检查异常两种: 可检查异常(checked exception):指在编译阶段就可以预测并处理的异…

    Java 2023年4月27日
    00
  • 微信小程序实现书架小功能

    下面我将为你详细讲解如何在微信小程序中实现书架小功能。 1. 准备工作 在开始实现之前,你需要安装并配置好微信小程序开发工具,同时了解一些基本的微信小程序开发知识。如果你还没有完成这些准备工作,可参考官方文档进行学习。 2. 创建页面 首先,需要在小程序中创建一个页面来展示书架。在微信小程序开发者工具中,点击新建页面,命名为bookshelf。同时,在根目录…

    Java 2023年5月23日
    00
  • 详解 Java中日期数据类型的处理之格式转换的实例

    下面是详解Java中日期数据类型的处理之格式转换的实例的完整攻略。 前言 在Java中,常用的日期数据类型有java.util.Date和java.time.LocalDateTime等。在处理日期时,我们有时需要把日期按照一定的格式进行转换,例如将2022-01-01转换成2022年01月01日。本文将对Java中日期格式转换进行详细讲解,并提供具体的代码…

    Java 2023年5月20日
    00
  • 微信小程序仿知乎实现评论留言功能

    下面我将为您详细讲解“微信小程序仿知乎实现评论留言功能”的完整攻略。 一、前置知识和准备工作 在开始编写代码前,需要准备好以下工具和知识: 微信开发者工具:用于开发和调试微信小程序,可在微信公众平台下载并安装。 知乎API:用于获取知乎的相关数据,需要向知乎开放平台申请。 Markdown渲染库:用于将知乎中的Markdown格式的文本转化成小程序可显示的格…

    Java 2023年5月23日
    00
  • JQuery标签页效果实例详解

    接下来我将为你详细讲解“JQuery标签页效果实例详解”的完整攻略。 概述 本文将介绍如何使用 jQuery 实现一个标签页效果。标签页是一种常见的网页布局方式,用户可以通过点击标签来切换不同的内容。在本文中,我们将使用 jQuery 和 CSS 实现一个简单的标签页效果。 实现步骤 创建 HTML 结构 首先需要创建一个 HTML 结构,包含多个标签和对应…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部