Spring全家桶面试题, 只补充细节版本

Spring全家桶面试题, 补充细节版本(2021优化版)

@$Spring Boot的启动流程,分为以下两大部分:

SpringApplication的实例化

  • 推断应用类型是否是Web环境

  • 设置初始化器(Initializer)

  • 设置监听器(Listener)

  • 推断应用入口类(Main)

SpringApplication.run方法

  • 获取SpringApplicationRunListeners

  • 准备配置环境ConfigurableEnvironment

  • 创建ApplicationContext应用上下文

  • ApplicationContext前置处理

  • ApplicationContext刷新

  • ApplicationContext后置处理

完成了实例化,下面开始调用run方法

复制代码
// 运行run方法
public ConfigurableApplicationContext run(String... args) {
   // 此类通常用于监控开发过程中的性能,而不是生产应用程序的一部分。
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();

   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();

   // 设置java.awt.headless系统属性,默认为true
   // Headless模式是系统的一种配置模式。在该模式下,系统缺少了显示设备、键盘或鼠标。
   configureHeadlessProperty();

   // KEY 1 - 获取SpringApplicationRunListeners
   SpringApplicationRunListeners listeners = getRunListeners(args);

   // 通知监听者,开始启动
   listeners.starting();
   try {
       ApplicationArguments applicationArguments = new DefaultApplicationArguments(
               args);

       // KEY 2 - 根据SpringApplicationRunListeners以及参数来准备环境
       ConfigurableEnvironment environment = prepareEnvironment(listeners,
               applicationArguments);
       
       configureIgnoreBeanInfo(environment);

       // 准备Banner打印器 - 就是启动Spring Boot的时候打印在console上的ASCII艺术字体
       Banner printedBanner = printBanner(environment);

       // KEY 3 - 创建Spring上下文
       context = createApplicationContext();

       // 注册异常分析器
       analyzers = new FailureAnalyzers(context);

       // KEY 4 - Spring上下文前置处理
       prepareContext(context, environment, listeners, applicationArguments,
               printedBanner);

       // KEY 5 - Spring上下文刷新
       refreshContext(context);

       // KEY 6 - Spring上下文后置处理
       afterRefresh(context, applicationArguments);

       // 发出结束执行的事件
       listeners.finished(context, null);

       stopWatch.stop();
       if (this.logStartupInfo) {
           new StartupInfoLogger(this.mainApplicationClass)
                  .logStarted(getApplicationLog(), stopWatch);
      }
       return context;
  }
   catch (Throwable ex) {
       handleRunFailure(context, listeners, exceptionReporters, ex);
       throw new IllegalStateException(ex);
  }
}

SpringBoot 自动装配

启动时扫描:SpringBoot 启动时,@EnableAutoConfiguration 触发对 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports` 的扫描,获取所有候选自动配置类。

条件过滤:通过条件注解(如 @Conditional)筛选出符合当前环境的自动配置类。

注册 Bean:自动配置类中的 @Bean 方法向容器注册组件,完成自动装配。

SpringBoot 的"自动装配"**不是黑魔法**,而是一条**"约定优于配置"的装配生产线**:

`spring-boot-autoconfigure` 模块里预置了上百个`@Configuration`类,它们会**根据你引入的 jar、配置的参数以及运行环境**,**条件化地**把 Bean 注入容器。

一句话:**"你加依赖,我配 Bean;你写参数,我改行为;什么都不要,我就按默认值跑。"**

下面按"面试可讲、源码可看、实战可用"三层展开。


一、面试口语版(3 分钟能说清)

  1. 启动入口

`@SpringBootApplication` =

`@EnableAutoConfiguration`(开自动装配)

  • `@ComponentScan`(扫自己写的组件)

  • `@SpringBootConfiguration`(声明配置类)。

  1. 加载坐标

`EnableAutoConfiguration` 导入 `AutoConfigurationImportSelector`,它从

`META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`

读取 140+ 个自动配置类的全限定名(Spring Boot 2.7+ 废弃 `spring.factories`,3.x 彻底移除此文件)。

  1. 条件判断

每个自动配置类头上都挂着一堆 `@ConditionalOnXxx`:

  • `@ConditionalOnClass` classpath 里有指定类才生效

  • `@ConditionalOnMissingBean` 容器里没这 Bean 才帮你配

  • `@ConditionalOnProperty` 配置项开关

  • ......(还有 10 来种)

举例:`DataSourceAutoConfiguration` 只在

classpath 下有 `javax.sql.DataSource` 且用户没自己配 `DataSource` Bean 时才启动。

  1. 参数绑定

生效后,配置类里用 `@EnableConfigurationProperties` 把

`application.yml` 中的 `spring.datasource.*` 绑定到 `DataSourceProperties`,

再调用 `DataSourceBuilder` 创建 `HikariDataSource` Bean 并注册。

  1. 留给用户的"钩子"
  • 完全替代:自己写一个 `@Bean`,自动配置就退让(`@ConditionalOnMissingBean`)。

  • 微调参数:改 `application.yml` 即可。

  • 关闭某段:

`spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration`


二、源码速读路线(能点到文件名)

  1. SpringApplication.run

  1. `refresh()` → `invokeBeanFactoryPostProcessors()`

  1. `ConfigurationClassPostProcessor` 解析 `@Configuration`

  1. `AutoConfigurationImportSelector.selectImports()`

读取 `META-INF/spring/*.imports` 文件,得到 `List<String> candidateConfigurations`

  1. `ConditionEvaluator` 按 `@ConditionalOnXxx` 过滤,生成 `MatchResult`

  1. 剩余配置类被 `ConfigurationClassParser` 加载,其内部 `@Bean` 方法被 `Cglib` 增强后注册到 `DefaultListableBeanFactory`

三、实战自定义 starter(10 行代码能跑通)

需求:项目里只要引入 `my-sms-spring-boot-starter`,就自动注入一个 `SmsTemplate`。

  1. 新建模块 `my-sms-spring-boot-autoconfigure`

```java

@Configuration

@ConditionalOnClass(SmsTemplate.class)

@EnableConfigurationProperties(SmsProperties.class)

public class SmsAutoConfiguration {

@Bean

@ConditionalOnMissingBean

public SmsTemplate smsTemplate(SmsProperties props) {

return new SmsTemplate(props.getAccessKey(), props.getSecret());

}

}

```

  1. 新建 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`

```

com.demo.sms.SmsAutoConfiguration

```

  1. 再包一个 `my-sms-spring-boot-starter`(空 jar,只依赖上面 autoconfigure 模块 + 业务 SDK)

  2. 业务方使用

```xml

<dependency>

<groupId>com.demo</groupId>

<artifactId>my-sms-spring-boot-starter</artifactId>

</dependency>

```

```yaml

sms.access-key=AKxxx

sms.secret=SECxxx

```

启动即得可注入的 `SmsTemplate`。


四、常见坑 & 调优

  1. 循环依赖报 `BeanCurrentlyInCreationException`

→ 检查自动配置顺序,用 `@AutoConfigureAfter/@AutoConfigureBefore` 调整。

  1. 启动慢

→ 打开 `debug=true` 或 `spring.boot.autoconfigure.condition.OnClassCondition=TRACE` 看哪些条件未命中,排除无用配置。

  1. 重复 Bean

→ 用 `spring.autoconfigure.exclude` 或在自定义 starter 里加 `@ConditionalOnMissingBean`。


一句话收拢

自动装配 = **"在正确的时间,把正确的 Bean,按正确的配置,塞进容器"**;

而 SpringBoot 把这套流程固化成了**条件注解 + 配置类 + META-INF 索引**,

既让**用户零配置**,又留足**扩展/覆盖/排错**的口子,这才是它"开箱即用"的本质。

面试口诀(3 句背完)
  1. 入口一注解:

`@SpringBootApplication` 里藏 `@EnableAutoConfiguration`,开启自动装配。

  1. 加载两步走:

① 读文件:`META-INF/spring/*.imports` 拿出 140+ 自动配置类。

② 做判断:`@ConditionalOnClass/@OnMissingBean` 等条件过滤,只留需要的。

  1. 结果零配置:

条件成立就帮你注册 Bean,参数用 `@ConfigurationProperties` 绑定到 yml;

你写自己的 Bean 或改 yml,就能覆盖默认,实现"开箱即用"。

SPI 配置文件

SPI 配置文件变更 SpringBoot 3 中,自动配置类的注册文件从 META-INF/spring.factories 迁移到了 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (文本文件,每行一个自动配置类全类名)。原因:spring.factories 是 Spring 传统的 SPI 格式,而新格式更简洁,且避免了与其他 SPI 配置的冲突。示例(AutoConfiguration.imports):

com.example.config.MyAutoConfiguration

com.example.config.UserAutoConfiguration

相关推荐
用户6120414922133 小时前
使用JSP+Servlet+JavaBean做的课程后台管理系统
java·javascript·mysql
卖丝袜的小郎君3 小时前
阿里云OSS使用预签名URL上传文件,状态码返回403,报SignatureDoesNotMatch异常
后端
又过一个秋3 小时前
dpdk-2.helloword源码
后端
乌暮3 小时前
数据库--JDBC编程
java·数据库·学习
摇滚侠3 小时前
Spring Boot3零基础教程,SpringSecurity 测试,笔记81
spring boot·笔记·后端
小白黑科技测评3 小时前
2025 年视频去水印工具实测:擦擦视频双版本解析一键去字幕与多格式兼容能力
java·人工智能·音视频·智能电视·1024程序员节
华仔啊3 小时前
Go 语言未来会取代 Java 吗?别争了,先看完这篇再说
java·后端·go
IT_陈寒3 小时前
SpringBoot 3.2新特性实战:这5个隐藏功能让我开发效率提升50%
前端·人工智能·后端