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日

相关文章

  • 六个Java集合使用时需要注意的事项

    六个Java集合使用时需要注意的事项 在Java开发中,集合框架扮演了非常重要的角色。它可以通过高效地存储和访问数据来简化我们的开发工作。本文将介绍在使用Java集合框架时需要注意的六件事。 1. 选择合适的集合类型 在使用集合框架时,我们需要根据要解决的问题选择合适的集合类型。例如,如果我们需要用于快速查找元素和按键访问元素的数据结构,则HashMap可能…

    Java 2023年5月25日
    00
  • 详解java数组进行翻转的方法有哪些

    详解Java数组进行翻转的方法有哪些 Java中提供了多种翻转数组的方法,可以通过修改数组元素的顺序或者创建新数组来实现。本文将为大家介绍四种常用的翻转数组的方法。 1. 利用for循环实现 public static int[] reverseArray(int[] array) { int length = array.length; int[] res…

    Java 2023年5月26日
    00
  • Mybatis-Plus接口BaseMapper与Services使用详解

    关于“Mybatis-Plus接口BaseMapper与Services使用详解”的攻略,我来详细讲解一下。 一、前言 Mybatis-Plus是Mybatis的一个增强工具,可以帮助我们快速地开发数据库应用程序。Mybatis-Plus提供了BaseMapper和BaseService两个接口,可以非常方便地进行数据操作。接下来我将对这两个接口进行详细的讲…

    Java 2023年5月20日
    00
  • JavaWeb入门:ServletContext详解和应用

    JavaWeb入门:ServletContext详解和应用 ServletContext是JavaEE中一个非常重要的Web接口,它代表了Servlet容器提供的一个Web应用程序的环境,可以用来从应用程序中获取初始化参数、获取上下文路径、获取资源路径、记录日志信息等。 ServletContext对象 ServletContext对象是由Servlet容器…

    Java 2023年6月15日
    00
  • Sprint Boot @Controller使用方法详解

    @Controller是Spring Boot中的一个注解,它用于标记一个类为控制器类。在使用Spring Boot开发Web应用程序时,@Controller是非常有用的。本文将详细介绍@Controller的作用和使用方法,并提供两个示例说明。 @Controller的作用 @Controller的作用是标记一个类为控制器类。控制器类是指处理HTTP请求…

    Java 2023年5月5日
    00
  • Java ArrayList中存放引用数据类型的方式

    Java的ArrayList是一种动态数组类型,它可以存储引用数据类型,即存储对象的引用。下面是Java ArrayList存放引用数据类型的方式的完整攻略。 1. 创建一个ArrayList 使用Java中的ArrayList类来创建一个ArrayList,代码如下: ArrayList<Object> arrayList = new Arra…

    Java 2023年5月26日
    00
  • JSP入门之HelloWorld程序实例

    JSP入门之HelloWorld程序实例 简介 JSP(Java Server Pages)是一种动态网页开发技术,可以将Java代码嵌入到HTML页面中,动态生成HTML页面。 HelloWorld程序是最简单的JSP程序,通常作为起步项目,通过实现它可以快速体验JSP的开发过程。 下面是一个简单的HelloWorld程序实例。 示例1 创建一个名为ind…

    Java 2023年6月15日
    00
  • SpringBoot 表单提交全局日期格式转换器实现方式

    下面就是 “SpringBoot 表单提交全局日期格式转换器实现方式” 的完整攻略。 1. 背景 在 SpringBoot 中,表单提交中的日期格式转换一直是困扰开发者的问题。SpringBoot 提供了很多方式解决这个问题,其中最简单的方式就是通过实现全局日期格式转换器来解决。 2. 实现方式 以下是实现全局日期格式转换器的步骤: 2.1 新建全局日期格式…

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