本轮 SpringBoot2核心功能面试题库(带答案)
生成时间:2026-05-24 21:07
【面试题】1. @SpringBootApplication注解的三大核心注解是什么?它们的职责分别是什么?
【标准答案】 @SpringBootApplication是一个组合注解,包含三个核心注解:
1. @SpringBootConfiguration
- 本质就是@Configuration,标记这是一个配置类
- 允许在类中定义@Bean方法
2. @EnableAutoConfiguration
- 核心注解,开启自动配置
- 通过@Import导入AutoConfigurationImportSelector
- 扫描META-INF/spring.factories或AutoConfiguration.imports文件,加载所有自动配置类
- 根据条件注解@ConditionalXxx判断是否生效
3. @ComponentScan
- 开启组件扫描,默认扫描主类所在包及其子包
- 扫描@Controller、@Service、@Repository、@Component等注解的Bean
面试回答技巧:先说三个注解名字,再分别解释职责,最后强调@EnableAutoConfiguration是自动配置的入口。可以补充:exclude属性可以排除特定自动配置。
【面试题】2. SpringBoot的自动配置原理是什么?请详细说明加载流程。
【标准答案】 自动配置原理分为四个步骤:
第一步:启动类入口
- @EnableAutoConfiguration通过@Import导入AutoConfigurationImportSelector
第二步:加载候选配置类
- AutoConfigurationImportSelector读取META-INF/spring.factories(旧版)或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports(2.7+)
- 获取所有EnableAutoConfiguration对应的配置类全限定名
第三步:条件过滤
- 每个配置类上有@Conditional系列注解:
- @ConditionalOnClass:类路径存在某类才生效
- @ConditionalOnMissingBean:容器不存在某Bean才生效
- @ConditionalOnProperty:配置属性满足条件才生效
- 只有满足条件的配置类才会注册Bean
第四步:按需装配
- 如DispatcherServletAutoConfiguration,只在Web环境下生效
- 如DataSourceAutoConfiguration,只在有DataSource类且配置了数据源时生效
面试回答技巧:按"入口→加载→过滤→装配"四步走,强调条件注解是核心,SpringBoot不是一股脑全加载,而是按需装配。
【面试题】3. application.yml和application.properties加载顺序是怎样的?优先级如何?
【标准答案】 加载顺序(从高到低优先级):
- 命令行参数:--server.port=8081
- Java系统属性:-Dserver.port=8081
- 操作系统的环境变量:SERVER_PORT=8081
- jar包外部的application-{profile}.yml/properties
- jar包内部的application-{profile}.yml/properties
- jar包外部的application.yml/properties
- jar包内部的application.yml/properties
- @ConfigurationProperties注解类的默认值
关键规则:
- 外部配置覆盖内部配置
- 高优先级覆盖低优先级
- yml和properties同时存在,properties优先级更高(但推荐统一用yml)
- 相同属性会覆盖,不同属性会互补
面试回答技巧:核心记忆"命令行>外部>内部",实际开发中常用命令行参数或外部配置文件实现动态配置。
【面试题】4. @ConfigurationProperties和@Value注解有什么区别?各自的适用场景是什么?
【标准答案】
| 特性 | @ConfigurationProperties | @Value |
|---|---|---|
| 功能 | 批量绑定配置到Bean | 单个属性注入 |
| 松散绑定 | 支持(user-name可映射userName) | 不支持 |
| SpEL表达式 | 不支持 | 支持 |
| JSR303校验 | 支持@Validated | 不支持 |
| 复杂对象 | 支持Map、List、嵌套对象 | 不支持 |
@ConfigurationProperties适用场景:
- 配置项较多,需要统一管理
- 需要校验配置合法性
- 需要嵌套对象或集合
- 示例:数据库连接池配置、Redis配置
@Value适用场景:
- 只需注入个别属性
- 需要SpEL表达式计算
- 示例:@Value("${app.version}") private String version;
面试回答技巧:表格对比一目了然,强调@ConfigurationProperties更适合配置类,@Value更灵活轻量。可补充:@ConfigurationProperties需要配合@EnableConfigurationProperties或@Component使用。
【面试题】5. Bean的完整生命周期是怎样的?各个阶段的回调方法有哪些?
【标准答案】 Bean生命周期分为四个阶段:
阶段一:实例化(Instantiation)
- BeanDefinition转换为Bean对象
- 调用构造器创建实例
- 扩展点:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
阶段二:属性赋值(Populate)
- 依赖注入,设置属性值
- 扩展点:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
- Aware接口回调:BeanNameAware、BeanFactoryAware、ApplicationContextAware
阶段三:初始化(Initialization)
- BeanPostProcessor.postProcessBeforeInitialization()
- @PostConstruct注解方法
- InitializingBean.afterPropertiesSet()
- 自定义init-method
- BeanPostProcessor.postProcessAfterInitialization()
阶段四:销毁(Destruction)
- @PreDestroy注解方法
- DisposableBean.destroy()
- 自定义destroy-method
面试回答技巧:用口诀记忆"实例化→属性赋值→初始化→销毁",重点记住三个阶段的核心回调:@PostConstruct/InitializingBean、@PreDestroy/DisposableBean。可以强调BeanPostProcessor是AOP的关键。
【面试题】6. Spring AOP的代理方式有哪两种?什么情况下用JDK动态代理,什么情况下用CGLIB?
【标准答案】 两种代理方式:
1. JDK动态代理
- 基于接口实现
- 要求目标类实现接口
- 使用java.lang.reflect.Proxy生成代理对象
- SpringBoot 2.x默认策略(proxy-target-class=false)
2. CGLIB代理
- 基于继承实现
- 通过生成目标类的子类
- 不能代理final类和final方法
- SpringBoot中proxy-target-class=true时使用
使用规则:
- 目标类实现了接口:默认JDK动态代理
- 目标类没有实现接口:必须用CGLIB
- 强制使用CGLIB:@EnableAspectJAutoProxy(proxyTargetClass=true)
SpringBoot 2.x的变化:
- 默认proxy-target-class=true,优先CGLIB
- 统一代理方式,避免混淆
面试回答技巧:先说两种代理区别,再强调SpringBoot 2.x默认CGLIB,可以追问"为什么默认改了?答案是统一行为、避免代理对象类型不一致问题"。
【面试题】7. @Transactional注解的传播行为有哪些?最常用的几个是什么?
【标准答案】 七种传播行为:
| 传播行为 | 说明 | 使用场景 |
|---|---|---|
| REQUIRED(默认) | 有事务则加入,无则新建 | 最常用,90%场景 |
| REQUIRES_NEW | 总是新建事务,挂起当前 | 独立日志、审计记录 |
| SUPPORTS | 有事务则加入,无则非事务执行 | 查询方法 |
| NOT_SUPPORTED | 非事务执行,挂起当前事务 | 性能优化场景 |
| MANDATORY | 必须在事务中调用,否则抛异常 | 强校验场景 |
| NEVER | 必须非事务调用,否则抛异常 | 强校验场景 |
| NESTED | 嵌套事务,支持部分回滚 | 复杂业务分步处理 |
最常用的三个:
- REQUIRED:默认值,保证方法在事务中执行
- REQUIRES_NEW:独立事务,不受外层事务影响
- NESTED:嵌套事务,内层可单独回滚
面试回答技巧:重点说REQUIRED和REQUIRES_NEW的区别,举例:REQUIRES_NEW常用于日志记录,即使业务回滚,日志也要保存。
【面试题】8. SpringBoot如何实现多数据源配置?事务如何管理?
【标准答案】 多数据源配置步骤:
第一步:配置数据源
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/db1
username: root
password: root
secondary:
url: jdbc:mysql://localhost:3306/db2
username: root
password: root第二步:配置DataSource Bean
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties(prefix="spring.datasource.primary")
public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); }
@Bean
@ConfigurationProperties(prefix="spring.datasource.secondary")
public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); }
}第三步:配置事务管理器
@Bean
@Primary
public PlatformTransactionManager primaryTransactionManager(DataSource primaryDataSource) {
return new DataSourceTransactionManager(primaryDataSource);
}事务管理关键:
- 每个数据源配置独立的事务管理器
- 使用@Transactional(value="primaryTransactionManager")指定
- 跨数据源事务需要分布式事务(JTA/Seata)
面试回答技巧:强调"一个数据源配一个事务管理器",可以追问"跨数据源事务怎么办?答案是分布式事务框架"。
【面试题】9. SpringBoot的Actuator提供了哪些核心端点?如何自定义健康检查?
【标准答案】 核心端点:
| 端点 | 功能 | 敏感信息 |
|---|---|---|
| /health | 应用健康状态 | 可能暴露数据库连接状态 |
| /info | 应用信息 | 无 |
| /metrics | 性能指标 | 无 |
| /env | 环境变量 | 可能暴露配置 |
| /beans | Bean列表 | 无 |
| /mappings | URL映射 | 无 |
| /threaddump | 线程快照 | 无 |
自定义健康检查:
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 自定义检查逻辑
boolean healthy = checkExternalService();
if (healthy) {
return Health.up()
.withDetail("service", "external-service")
.withDetail("status", "available")
.build();
}
return Health.down()
.withDetail("service", "external-service")
.withDetail("status", "unavailable")
.build();
}
}安全暴露配置:
management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: when-authorized面试回答技巧:强调生产环境要控制端点暴露,show-details设为when-authorized或never,避免敏感信息泄露。
【面试题】10. SpringBoot打包后的jar包结构是怎样的?如何实现分层打包优化Docker镜像?
【标准答案】 SpringBoot JAR包结构:
app.jar
├── BOOT-INF/
│ ├── classes/ # 应用类文件
│ └── lib/ # 依赖jar包
├── META-INF/
│ └── MANIFEST.MF # 主清单文件
└── org/springframework/boot/loader/ # SpringBoot加载器分层打包原理:
- SpringBoot 2.3+支持分层JAR
- 按依赖变化频率分层:dependencies > spring-boot-loader > snapshot-dependencies > application
- Docker构建时可缓存不变的层
分层打包配置:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
</plugin>Dockerfile优化示例:
FROM java:8-alpine as builder
WORKDIR application
COPY target/app.jar app.jar
RUN java -Djarmode=layertools -jar app.jar extract --destination extracted
FROM java:8-alpine
WORKDIR application
COPY --from=builder application/extracted/dependencies/ ./
COPY --from=builder application/extracted/spring-boot-loader/ ./
COPY --from=builder application/extracted/snapshot-dependencies/ ./
COPY --from=builder application/extracted/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]面试回答技巧:核心说"依赖层不变,应用层常变",Docker构建时先复制依赖层可缓存,只有代码变化才重建应用层,大幅减少构建时间。
总结
本批题目覆盖:自动配置原理、配置管理、Bean生命周期、AOP代理、事务传播、多数据源、Actuator监控、分层打包等核心考点。建议结合源码深入理解条件注解和启动流程。