SpringBoot 之启动流程

简介: SpringBoot 是一个基于 Spring 框架的快速开发框架,旨在简化 Spring 应用程序的开发和部署。在本文中,我们将深入分析 SpringBoot 启动过程的源代码,并提供必要的解释和说明。

SpringBoot 是一个基于 Spring 框架的快速开发框架,旨在简化 Spring 应用程序的开发和部署。在本文中,我们将深入分析 SpringBoot 启动过程的源代码,并提供必要的解释和说明。
SpringBoot启动过程简介
SpringBoot应用程序的启动过程可以分为以下几个步骤:

加载应用程序上下文
扫描应用程序中的所有组件
自动配置应用程序环境
启动嵌入式Web服务器

在下面的章节中,我们将逐一分析这些步骤的源代码。
加载应用程序上下文
SpringBoot 应用程序的上下文是一个包含所有应用程序组件的容器。在启动过程中,SpringBoot 会加载并初始化这个容器。
这个步骤的源代码在SpringApplication类中。具体来说,SpringApplication类的run方法是这个过程的入口点。在这个方法中,Spring Boot会通过调用createApplicationContext方法来创建应用程序上下文。
下面是createApplicationContext方法的源代码:
protected ConfigurableApplicationContext createApplicationContext() {

Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
    try {
        switch (this.webApplicationType) {
            case SERVLET:
                contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
                break;
            case REACTIVE:
                contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
                break;
            default:
                contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
        }
    }
    catch (ClassNotFoundException ex) {
        throw new IllegalStateException(
                "Unable to create a default ApplicationContext, " +
                "please specify an ApplicationContextClass", ex);
    }
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);

}
复制代码
在这个方法中,SpringBoot 会根据应用程序类型(Servlet或Reactive)选择合适的上下文类。然后,它会使用 Java 反射机制来实例化这个类并返回一个可配置的应用程序上下文对象。
扫描应用程序中的所有组件
在上一步中,SpringBoot创建了应用程序上下文。在这一步中,SpringBoot会扫描应用程序中的所有组件并将它们注册到应用程序上下文中。
这个步骤的源代码在SpringApplication类中的scan方法中。具体来说,在这个方法中,SpringBoot 会创建一个SpringBootBeanDefinitionScanner对象,并使用它来扫描应用程序中的所有组件。
下面是scan方法的源代码:
private void scan(String... basePackages) {

if (ObjectUtils.isEmpty(basePackages)) {
    return;
}
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(
        this.includeFilters, this.excludeFilters, this.resourceLoader);
scanner.setResourceLoader(this.resourceLoader);
scanner.setEnvironment(this.environment);
scanner.setIncludeAnnotationConfig(this.useAnnotatedConfig);
scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
    @Override
    protected boolean matchClassName(String className) {
        return getExcludeClassNames().contains(className);
    }
});
for (String basePackage : basePackages) {
    scanner.findCandidateComponents(basePackage).forEach(this.componentDefinitions::add);
}

}
复制代码
在这个方法中,SpringBoot 会创建一个ClassPathScanningCandidateComponentProvider对象,并使用它来扫描应用程序中的所有组件。这个对象会扫描指定包路径下的所有类,并将它们转换为 Spring 的 Bean 定义。这些 Bean 定义将被注册到应用程序上下文中。
自动配置应用程序环境
在上一步中,SpringBoot将应用程序中的所有组件注册到应用程序上下文中。在这一步中,SpringBoot将自动配置应用程序环境,包括配置数据源、事务管理器、JPA等。
这个步骤的源代码在SpringApplication类中的configureEnvironment方法中。在这个方法中,Spring Boot会创建一个SpringApplicationRunListeners对象,并使用它来配置应用程序环境。
下面是configureEnvironment方法的源代码:
private void configureEnvironment(ConfigurableEnvironment environment, String[] args) {

if (this.addCommandLineProperties) {
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    environment.getPropertySources().addLast(new CommandLinePropertySource(applicationArguments));
}
this.listeners.environmentPrepared(environment);
if (this.logStartupInfo) {
    this.logStartupInfo(environment);
}
ConfigurationPropertySources.attach(environment);
Binder.get(environment).bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(this.sources));
if (!this.isCustomEnvironment) {
    EnvironmentConverter.configureEnvironment(environment, this.deduceEnvironmentClass());
}
this.listeners.environmentPrepared(environment);

}
复制代码
在这个方法中,SpringBoot 会创建一个ApplicationArguments对象,并将其转换为一个命令行属性源。然后,它会调用listeners中的environmentPrepared方法来通知应用程序环境已经准备好了。随后,SpringBoot 会绑定属性源到应用程序环境中,并调用listeners中的environmentPrepared方法来通知应用程序环境已经准备好了。
启动嵌入式Web服务器
在上一步中,SpringBoot 将应用程序环境自动配置完成。在这一步中,SpringBoot 将启动嵌入式Web服务器,以便应用程序能够提供 Web 服务。
这个步骤的源代码在SpringApplication类中的run方法中。具体来说,在这个方法中,SpringBoot 会根据应用程序类型(Servlet或Reactive)选择合适的嵌入式Web服务器,并使用它来启动应用程序。
下面是run方法的源代码:
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;

}
复制代码
在这个方法中,SpringBoot 会使用一个StopWatch对象来计算应用程序启动时间。然后,它会调用listeners中的starting方法来通知应用程序即将启动。接着,SpringBoot 会准备应用程序环境,并使用它来创建应用程序上下文。随后,SpringBoot 会调用listeners中的started方法来通知应用程序已经启动。最后,SpringBoot 会调用callRunners方法来运行所有的CommandLineRunner和ApplicationRunner组件。
总结
在本文中,我们深入分析了 SpringBoot 应用程序的启动过程的源代码。我们了解了 SpringBoot 如何加载应用程序上下文、扫描应用程序中的所有组件、自动配置应用程序环境以及启动嵌入式Web服务器。这些步骤的源代码展示了 SpringBoot 如何简化应用程序的开发和部署。

相关文章
|
6月前
|
前端开发 Java 应用服务中间件
SpringBoot-Run启动流程
探索Spring Boot启动流程,从加载配置、创建应用上下文、自动配置到启动内嵌服务器。启动类是入口点,`@SpringBootApplication`标记启动,`SpringApplication.run`启动应用。自动配置基于条件注解配置Bean,应用上下文由`SpringApplication`创建并刷新。内嵌服务器如Tomcat随应用启动,简化部署。理解此流程有助于深入掌握Spring Boot。
214 2
|
6月前
|
缓存 Java 程序员
springboot的启动流程总结
springboot的启动流程总结
|
6月前
|
设计模式 Java 容器
SpringBoot2 | SpringBoot启动流程源码分析(二)
SpringBoot2 | SpringBoot启动流程源码分析(二)
80 0
|
6月前
|
设计模式 Java 机器人
SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter
SpringBoot3自动配置流程 SPI机制 核心注解 自定义starter
|
1月前
|
前端开发 Java 数据安全/隐私保护
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
文章通过一个简单的SpringBoot项目,详细介绍了前后端如何实现用户登录功能,包括前端登录页面的创建、后端登录逻辑的处理、使用session验证用户身份以及获取已登录用户信息的方法。
189 2
用户登录前后端开发(一个简单完整的小项目)——SpringBoot与session验证(带前后端源码)全方位全流程超详细教程
|
5月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp小程序的销售项目流程化管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp小程序的销售项目流程化管理系统附带文章源码部署视频讲解等
65 3
|
1月前
|
NoSQL Java Redis
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
这篇文章介绍了如何使用Spring Boot整合Apache Shiro框架进行后端开发,包括认证和授权流程,并使用Redis存储Token以及MD5加密用户密码。
30 0
shiro学习四:使用springboot整合shiro,正常的企业级后端开发shiro认证鉴权流程。使用redis做token的过滤。md5做密码的加密。
|
1月前
|
XML Java 应用服务中间件
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
【Spring】运行Spring Boot项目,请求响应流程分析以及404和500报错
180 2
|
1月前
|
JSON 前端开发 JavaScript
优雅!Spring Boot 3.3 实现职责链模式,轻松应对电商订单流程
本文介绍如何使用 Spring Boot 3.3 实现职责链模式,优化电商订单处理流程。通过将订单处理的各个环节(如库存校验、优惠券核验、支付处理等)封装为独立的处理器,并通过职责链将这些处理器串联起来,实现了代码的解耦和灵活扩展。具体实现包括订单请求类 `OrderRequest`、抽象处理器类 `OrderHandler`、具体处理器实现(如 `OrderValidationHandler`、`VerifyCouponHandler` 等)、以及初始化职责链的配置类 `OrderChainConfig`。
|
3月前
|
XML Java 应用服务中间件
SpringBoot启动流程解析
SpringBoot启动流程解析
47 0

热门文章

最新文章