大佬用4000字带你彻底理解SpringBoot的运行原理!
ztj100 2025-08-02 22:49 2 浏览 0 评论
Spring Boot的运行原理
从前面创建的Spring Boot应用示例中可以看到,启动一个Spring Boot工程都是从SpringApplication.run()方法开始的。这个方法具体完成了哪些工作?@Spring-BootApplication注解的作用是什么?在本节内容中将找到答案。
SpringApplication启动类
通过查看SpringApplication.run()方法的源码可以看到,该方法首先生成Spring-Application的一个实例,然后调用实例的run()方法。下面来看一下SpringApplication构造函数的源码:
public SpringApplication(ResourceLoader resourceLoader,
Class...
primarySources) {
this.sources = new LinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
//①
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = new HashSet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
//②
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must
not be null");
this.primarySources = new LinkedHashSet(Arrays.asList
(primarySources));
this.webApplicationType =
WebApplicationType.deduceFrom
Classpath();
//③
this.setInitializers(this.getSpringFactoriesInstances(Applica
tion
ContextInitializer.class));
//④
this.setListeners(this.getSpringFactoriesInstances
(ApplicationListener.class));
//⑤
this.mainApplicationClass =
this.deduceMainApplicationClass();
}
注释①:打印启动信息。
注释②:表示Bean是否要以懒加载的方式进行实例化。
注释③:初始化WebApplicationType的类型,主要包括REACTIVE、SERVLET和NONE三种类型。
注释④:加载
ApplicationContextInitializer类。
注释⑤:加载ApplicationListener类。
注释④和⑤是加载META-INF/spring.factories文件中配置的
ApplicationContext-Initializer和ApplicationListener类。具体配置代码如下:
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplica
tion
ContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextI
nitializer,\
org.springframework.boot.context.config.DelegatingApplication
ContextInitializer,\
org.springframework.boot.rsocket.context.RSocketPortInfoAppli
cation
ContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicatio
n
ContextInitializer
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicati
onListener,\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPos
t
Processor,\
org.springframework.boot.context.FileEncodingApplicationListe
ner,\
org.springframework.boot.context.config.AnsiOutputApplication
Listener,\
org.springframework.boot.context.config.ConfigFileApplication
Listener,\
org.springframework.boot.context.config.DelegatingApplication
Listener,\
org.springframework.boot.context.logging.ClasspathLoggingAppl
ication
Listener,\
org.springframework.boot.context.logging.LoggingApplicationLi
stener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApp
lication
Listener
通过上面的构造函数可以看到,SpringApplication类的主要的工作是确定Web应用类型、加载上下文初始化器及监听器等。
接下来看重要的部分,即SpringApplication实例的run()方法,具体源代码如下:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter>
exceptionReporters =
new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners =
this.getRunListeners
(args);
//①
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new
Default
ApplicationArguments(args);
ConfigurableEnvironment environment =
this.prepareEnvironment
(listeners, applicationArguments);
//②
this.configureIgnoreBeanInfo(environment);
Banner printedBanner =
this.printBanner(environment);
context = this.createApplicationContext();
//③
exceptionReporters =
this.getSpringFactoriesInstances
(SpringBootExceptionReporter.class, new Class[]
{ConfigurableApplication
Context.class}, context);
this.prepareContext(context, environment,
listeners,
applicationArguments, printedBanner);
//④
this.refreshContext(context);
//⑤
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new
StartupInfoLogger(this.mainApplicationClass)).
logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
//⑥
this.callRunners(context, applicationArguments);
//⑦
} catch (Throwable var10) {
this.handleRunFailure(context, var10,
exceptionReporters,
listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
//⑧
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9,
exceptionReporters,
(SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
注释①:初始化监听器,并开启监听器进行事件监听。
注释②:准备上下文环境,包括运行机器的环境变量、应用程序启动的变量和配置文件的变量等。初始化上下文环境后,启动监听器
listeners.environment-Prepared(environment)。
注释③:初始化应用上下文。根据WebApplicationType类型的不同,生成的上下文也不同。如果是SERVLET,则对应生成
AnnotationConfigServletWebServer-ApplicationContext;如果是REACTIVE,则对应生成AnnotationConfigReactive
WebServerApplicationContext。默认生成
AnnotationConfigApplicationContext。
注释④:刷新应用上下文的准备工作。此处主要用于设置容器环境,启动监听器listeners.contextPrepared(context),加载启动类,并调用listeners.contextLoaded (context)方法。
注释⑤:刷新应用上下文,主要用于进行自动化装配和初始化IoC容器。
注释⑥:容器启动事件。
注释⑦:如果有用户定义的CommandLineRunner或者
ApplicationRunner,则遍历执行它们。
注释⑧:容器运行事件。
通过分析源代码,总结出Spring Boot启动的主要流程如图3.4所示。
通过分析源代码还可以发现,事件监听是Spring框架中重要的一部分。Spring提供了多种类型的事件,常用的如表3.1所示。
@SpringBootApplication注解
在Spring Boot的入口类中,有一个重要的注解@SpringBootApplication,本节将分析该注解的作用。首先查看@SpringBootApplication的源代码,具体如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type =
FilterType.CUSTOM,
classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes =
AutoConfiguration
ExcludeFilter.class) })
public @interface SpringBootApplication {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = ComponentScan.class, attribute
= "base
Packages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute
= "base
PackageClasses")
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
通过源码可以看到,@SpringBootApplication是一个复合注解,包括@Component-Scan、@EnableAutoConfiguration和@SpringBootConfiguration等。下面具体分析这3个注解。
1. @ComponentScan注解
在第1章中讲过Bean的注解,如@Service、@Repository、@Component和@Controller等。@ComponentScan注解可以自动扫描被以上注解描述的Bean并将其加载到IoC容器中。@ComponentScan注解还有许多属性,通过这些属性可以更准确地指定哪些Bean被扫描并注入。
basePackages:指定需要扫描的包路径。
basePackageClasses:指定类,并扫描该类所在包下的所有组件。
includeFilters:指定哪些类可以通过扫描。
excludeFilters:指定哪些类不被扫描。
lazyInit:指定扫描的对象是否要懒加载。
resourcePattern:指定符合条件的类文件。
2. @EnableAutoConfiguration注解
@EnableAutoConfiguration注解是Spring Boot实现自动化配置加载的核心注解。通过@Import注入一个名为
AutoConfigurationImportSelector的类,Spring-FactoriesLoader类加载类路径下的META-INF/spring.factories文件来实现自动配置加载的过程。其中,spring.factories文件配置了
org.springframework.boot.autoconfigure.EnableAutoConfiguration属性值,可以加载配置了@Configuration注解的类到IoC容器中。
3. @SpringBootConfiguration注解
@SpringBootConfiguration注解的功能类似于@Configuration注解,声明当前类是一个配置类,它会将当前类中有@Bean注解的实例加载到IoC容器中。
相关推荐
- Java的SPI机制详解
-
作者:京东物流杨苇苇1.SPI简介SPI(ServiceProvicerInterface)是Java语言提供的一种接口发现机制,用来实现接口和接口实现的解耦。简单来说,就是系统只需要定义接口规...
- 一文读懂 Spring Boot 启动原理,开发效率飙升!
-
在当今的Java开发领域,SpringBoot无疑是最热门的框架之一。它以其“约定大于配置”的理念,让开发者能够快速搭建和启动应用,极大地提高了开发效率。但是,你是否真正了解Spring...
- ServiceLoader
-
ServiceLoader是Java提供的一种服务发现机制(ServiceProviderInterface,SPI)...
- 深入探索 Spring Boot3 中的自定义扩展操作
-
在当今互联网软件开发领域,SpringBoot无疑是最受欢迎的框架之一。随着其版本迭代至SpringBoot3,它为开发者们带来了更多强大的功能和特性,其中自定义扩展操作更是为我们在项目开发中...
- Spring Boot启动过程全面解析:从入门到精通
-
一、SpringBoot概述SpringBoot是一个基于Spring框架的快速开发脚手架,它通过"约定优于配置"的原则简化了Spring应用的初始搭建和开发过程。...
- Spring Boot 3.x 自定义 Starter 详解
-
今天星期六,继续卷springboot3.x。在SpringBoot3.x中,自定义Starter是封装和共享通用功能、实现“约定优于配置”理念的强大机制。通过创建自己的Starte...
- Spring Boot 的 3 种动态 Bean 注入技巧
-
在SpringBoot开发中,动态注入Bean是一种强大的技术,它允许我们根据特定条件或运行时环境灵活地创建和管理Bean。相比于传统的静态Bean定义,动态注入提供了更高的灵活性和可...
- 大佬用4000字带你彻底理解SpringBoot的运行原理!
-
SpringBoot的运行原理从前面创建的SpringBoot应用示例中可以看到,启动一个SpringBoot工程都是从SpringApplication.run()方法开始的。这个方法具体完成...
- Springboot是如何实现自动配置的
-
SpringBoot的自动配置功能极大地简化了基于Spring的应用程序的配置过程。它能够根据类路径中的依赖和配置文件中的属性,自动配置应用程序。下面是SpringBoot实现自动配置的...
- Spring Boot3.x 应用的生命周期深度解析
-
SpringBoot应用的生命周期可以清晰地划分为三个主要阶段:启动阶段(Startup)...
- Springboot 启动流程及各类事件生命周期那点事
-
前言本文通过Springboot启动方法分析SpringApplication逻辑。从静态run方法执行到各个阶段发布不同事件完成整个应用启动。...
- Spring框架基础知识-常用的接口1
-
BeanDefinition基本概念BeanDefinition是Spring框架中描述bean配置信息的核心接口,它包含了创建bean实例所需的所有元数据。...
- Java 技术岗面试全景备战!从基础到架构的系统性通关攻略分享
-
Java技术岗的面试往往是一项多维度的能力检验。本文将会从核心知识点、项目经验到面试策略,为你梳理一份系统性的备战攻略!...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)