专栏名称: 芋道源码
纯 Java 源码分享公众号,目前有「Dubbo」「SpringCloud」「Java 并发」「RocketMQ」「Sharding-JDBC」「MyCAT」「Elastic-Job」「SkyWalking」「Spring」等等
51好读  ›  专栏  ›  芋道源码

SpringBoot启动原理详解(图文全面总结)

芋道源码  · 公众号  · Java  · 2025-03-18 09:30

正文

👉 这是一个或许对你有用 的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入 芋道快速开发平台 知识星球。 下面是星球提供的部分资料:

👉 这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、 商城 、支付、工作流、大屏报表、微信公众号、 ERP CRM AI 大模型 等等功能:

  • Boot 多模块架构:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 微服务架构:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 双版本

来源:江南一点雨


虽然我们在日常开发中,Spring Boot 使用非常多,算是目前 Java 开发领域一个标配了,但是小伙伴们仔细想想自己的面试经历,和 Spring Boot 相关的面试题都有哪些?个人感觉应该是比较少的,Spring Boot 本质上还是曾经 SSM 那一套,只是通过各种 starter 简化了配置而已,其他都是一模一样的,所以 Spring Boot 中很多面试题还是得回归到 Spring 中去解答!当然这并不是说 Spring Boot 中没什么可问的,Spring Boot 中其实也有一个非常经典的面试题,那就是 Spring Boot 的启动原理是什么?今天就来和各位小伙伴聊一下这个问题。

其实之前和小伙伴们聊过相关的问题,不过都是零散的,没有系统梳理过,之前也带领小伙伴们自定义过一个 starter,相信各位小伙伴对于 starter 的原理也有一定了解,所以今天这篇文章一些过于细节的内容我就不赘述了。

一 @SpringBootApplication

要说 Spring Boot 的自动化配置,那必须从项目的启动类 @SpringBootApplication 说起,这是整个 Spring Boot 宇宙的起点,我们先来看下这个注解:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type 
= FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication 
{

}

可以看到, @SpringBootApplication 注解组合了多个常见注解的功能,其中:

  • 前四个是元注解,这里我们不做讨论。
  • 第五个 @SpringBootConfiguration 是一个支持配置类的注解,这里我们也不做讨论。
  • 第六个 @EnableAutoConfiguration 这个注解就表示开启自动化配置,这是我们今天要聊得重点。
  • 第七个 @ComponentScan 是一个包扫描注解,为什么 Spring Boot 项目中的 Bean 只要放对位置就会被自动扫描到,和这个注解有关。

别看这里注解多,其实真正由 Spring Boot 提供的注解一共就两个,分别是 @SpringBootConfiguration @EnableAutoConfiguration 两个,其他注解在 Spring Boot 出现之前就已经存在多年了。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

二 @EnableAutoConfiguration

接下来我们来看看 @EnableAutoConfiguration 是如何实现自动化配置的。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration 
{

}

这个注解起关键作用的就是两个东西:

  1. @AutoConfigurationPackage :这个表示自动扫描各种第三方的注解
  2. @Import 则是在导入 AutoConfigurationImportSelector 配置类,这个配置类里边就是去加载各种自动化配置类的。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

三 AutoConfigurationImportSelector

AutoConfigurationImportSelector 类中的方法比较多,入口的地方则是 process 方法,所以我们这里就从 process 方法开始看起:

@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
 Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
   () -> String.format("Only %s implementations are supported, got %s",
     AutoConfigurationImportSelector.class.getSimpleName(),
     deferredImportSelector.getClass().getName()))
;
 AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
  .getAutoConfigurationEntry(annotationMetadata);
 this.autoConfigurationEntries.add(autoConfigurationEntry);
 for (String importClassName : autoConfigurationEntry.getConfigurations()) {
  this.entries.putIfAbsent(importClassName, annotationMetadata);
 }
}

从类名就可以看出来,跟自动化配置相关的对象是由 AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata); 进行加载的。

当然这里的 getAutoConfigurationEntry 方法实际上就是当前类提供的方法,我们来看下该方法:

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
 if (!isEnabled(annotationMetadata)) {
  return EMPTY_ENTRY;
 }
 AnnotationAttributes attributes = getAttributes(annotationMetadata);
 List configurations = getCandidateConfigurations(annotationMetadata, attributes);
 configurations = removeDuplicates(configurations);
 Set exclusions = getExclusions(annotationMetadata, attributes);
 checkExcludedClasses(configurations, exclusions);
 configurations.removeAll(exclusions);
 configurations = getConfigurationClassFilter().filter(configurations);
 fireAutoConfigurationImportEvents(configurations, exclusions);
 return new AutoConfigurationEntry(configurations, exclusions);
}

这里源码的方法命名都做的不错,基本上都能做到见名知意,小伙伴们日常开发中,应该向这样的命名思路看齐。接下来我们就来挨个看一下这里的关键方法。

3.1 isEnabled

首先调用 isEnabled 方法去判断自动化配置到底有没有开启,这个主要是因为我们及时在项目中引入了 spring-boot-starter-xxx 之后,我们也可以通过在 application.properties 中配置 spring.boot.enableautoconfiguration=false 来关闭所有的自动化配置。

相关源码如下:

protected boolean isEnabled(AnnotationMetadata metadata) {
 if (getClass() == AutoConfigurationImportSelector.class{
  return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.classtrue);
 }
 return true;
}

3.2 getCandidateConfigurations

接下来调用 getCandidateConfigurations 方法去获取所有候选的自动化配置类,这些候选的自动化配置类主要来自两个地方:

  1. 在之前的自定义 starter 中松哥和大家聊过,我们需要在 claspath\:META-INF/spring.factories 中定义出来所有的自动化配置类,这是来源一。
  2. Spring Boot 自带的自动化配置类,这个在之前的 vhr 视频中也和小伙伴们多次讲过, Spring Boot 自带的自动化配置类位于 spring-boot-autoconfigure-3.0.6.jar!\META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中。






请到「今天看啥」查看全文