Skip to content

SpringBoot2核心功能面试题库 ​

生成时间:2026-05-21 23:32


本轮 SpringBoot2核心功能面试题库(带答案) ​

【面试题】1. SpringBoot启动类上的@SpringBootApplication注解由哪些注解组合而成?它们各自的作用是什么? ​

【标准答案】 @SpringBootApplication是一个组合注解,由三个核心注解组成:

第一,@SpringBootConfiguration,本质就是@Configuration,标记这是一个配置类,允许在类中定义@Bean方法。

第二,@ComponentScan,开启组件扫描,默认扫描当前包及其子包下所有带@Component、@Service、@Repository、@Controller注解的类,把它们注册成Bean。

第三,@EnableAutoConfiguration,这是自动配置的核心,通过@Import导入AutoConfigurationImportSelector,读取META-INF/spring.factories或org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,加载所有自动配置类,再结合条件注解按需装配。

简单说:@Configuration负责定义Bean,@ComponentScan负责发现Bean,@EnableAutoConfiguration负责自动配置Bean。


【面试题】2. SpringBoot的条件注解@ConditionalOnProperty是如何工作的?实际项目中怎么用? ​

【标准答案】 @ConditionalOnProperty根据配置文件中的属性值决定是否生效。

核心属性有三个:

  • prefix:属性前缀
  • name或value:属性名
  • havingValue:期望值
  • matchIfMissing:属性不存在时是否生效,默认false

工作原理:容器启动时,会读取环境中的属性值,和havingValue比对,匹配则注册Bean,不匹配则跳过。

实际应用场景:开关控制。比如我要做一个短信服务,生产环境用阿里云,测试环境用Mock实现。配置文件里写sms.provider=aliyun,条件注解写@ConditionalOnProperty(prefix="sms", name="provider", havingValue="aliyun"),只有配置匹配时才生效。另一个Mock实现写havingValue="mock"。

关键是:条件注解在Bean定义阶段生效,不会创建不必要的Bean,节省资源。


【面试题】3. SpringBoot的配置文件加载顺序是怎样的?同名属性如何覆盖? ​

【标准答案】 配置加载顺序从高到低:

  1. 命令行参数,优先级最高,比如--server.port=8081
  2. Java系统属性,System.getProperties()
  3. 操作系统环境变量
  4. application-{profile}.yml/properties,比如application-dev.yml
  5. application.yml/properties,jar包外
  6. application.yml/properties,jar包内
  7. @PropertySource注解指定的配置文件
  8. 默认属性,SpringApplication.setDefaultProperties

覆盖规则很简单:同名属性,优先级高的覆盖低的。比如application.yml里server.port=8080,命令行写了--server.port=8081,最终生效8081。

实际开发中,我们常用多环境配置:application.yml写公共配置,application-dev.yml写开发环境特有配置,application-prod.yml写生产环境特有配置。启动时指定spring.profiles.active=dev或prod,对应的环境配置会覆盖公共配置中的同名属性。


【面试题】4. @ConfigurationProperties和@Value绑定配置有什么区别?怎么选择? ​

【标准答案】 区别主要体现在三个方面:

第一,绑定方式不同。@ConfigurationProperties是批量绑定,把整个配置块映射成一个Java对象,属性名自动匹配,支持松散绑定,比如my.app-name能映射到appName字段。@Value是单个属性注入,每个属性都要写@Value("${my.app-name}")。

第二,校验能力不同。@ConfigurationProperties配合@Validated可以做JSR303校验,比如@NotBlank、@Min(1),启动时校验,配置不合法直接报错。@Value没有校验能力。

第三,SpEL支持不同。@Value支持SpEL表达式,比如@Value("#{systemProperties['user.name']}")。@ConfigurationProperties不支持SpEL,只支持配置文件属性。

选择建议:配置项多、需要类型安全校验、需要复用,用@ConfigurationProperties。配置项少、简单场景、需要SpEL,用@Value。

实际项目推荐用@ConfigurationProperties,代码更清晰,维护更方便,IDE还有提示支持。


【面试题】5. BeanFactory和ApplicationContext有什么区别?SpringBoot启动用的是哪个? ​

【标准答案】 BeanFactory是Spring最基础的容器接口,提供Bean的获取和管理能力,采用延迟加载,调用getBean时才创建Bean。

ApplicationContext继承BeanFactory,扩展了更多功能:国际化、事件发布、资源加载、环境信息、AOP支持。默认采用立即加载,容器启动时就创建所有单例Bean。

区别总结:BeanFactory是基础容器,功能最少;ApplicationContext是高级容器,功能更全。

SpringBoot启动用的是ApplicationContext,具体实现类是AnnotationConfigServletWebServerApplicationContext。启动流程中,SpringApplication.run方法会创建ApplicationContext,调用refresh方法完成容器初始化,包括BeanFactory的创建、BeanDefinition的注册、Bean的实例化,最后返回ApplicationContext。

简单记忆:BeanFactory是引擎,ApplicationContext是整辆车。


【面试题】6. BeanPostProcessor和BeanFactoryPostProcessor的区别是什么?执行时机各是什么时候? ​

【标准答案】 BeanFactoryPostProcessor是BeanFactory的后置处理器,在BeanDefinition加载完成后、Bean实例化之前执行。可以修改BeanDefinition的属性,比如修改scope、lazy-init、property values。典型应用是PropertySourcesPlaceholderConfigurer,处理${...}占位符。

BeanPostProcessor是Bean的后置处理器,在Bean实例化后、初始化前后执行。有两个方法:postProcessBeforeInitialization在初始化方法之前调用,postProcessAfterInitialization在初始化方法之后调用。典型应用是AutowiredAnnotationBeanPostProcessor处理@Autowired、@Value注解,还有AOP代理创建。

执行时机:

  1. BeanFactoryPostProcessor:refresh的invokeBeanFactoryPostProcessors阶段
  2. Bean实例化
  3. BeanPostProcessor的Before方法
  4. 初始化方法(@PostConstruct、InitializingBean)
  5. BeanPostProcessor的After方法

一句话总结:BeanFactoryPostProcessor改定义,BeanPostProcessor改实例。


【面试题】7. Spring AOP中@Around、@Before、@AfterReturning、@AfterThrowing、@After的执行顺序是怎样的? ​

【标准答案】 执行顺序分两种情况:

正常执行时:

  1. @Around前半部分
  2. @Before
  3. 目标方法执行
  4. @AfterReturning
  5. @After
  6. @Around后半部分

异常执行时:

  1. @Around前半部分
  2. @Before
  3. 目标方法抛异常
  4. @AfterThrowing
  5. @After

关键点:@After是最终通知,无论正常还是异常都会执行,类似finally。@AfterReturning只在正常返回时执行,@AfterThrowing只在异常时执行。

如果同一个方法有多个切面,可以用@Order或实现Ordered接口控制顺序,数值越小优先级越高。@Order(1)的切面比@Order(2)先执行。

实际开发中,@Around最强大,可以控制目标方法是否执行、修改参数、修改返回值、捕获异常。其他通知适用于简单场景。


【面试题】8. SpringBoot的事件机制是怎么工作的?ContextRefreshedEvent在什么时机触发? ​

【标准答案】 Spring事件机制基于观察者模式,三个核心组件:

  1. ApplicationEvent:事件基类,自定义事件继承它
  2. ApplicationListener:事件监听器,实现onApplicationEvent方法
  3. ApplicationEventPublisher:事件发布器,通过ApplicationContext获取

SpringBoot内置事件按启动顺序:

  • ApplicationStartingEvent:启动开始
  • ApplicationEnvironmentPreparedEvent:环境准备完成
  • ApplicationContextInitializedEvent:容器初始化
  • ApplicationPreparedEvent:Bean定义加载完成
  • ContextRefreshedEvent:容器刷新完成
  • ApplicationStartedEvent:应用启动完成
  • ApplicationReadyEvent:应用就绪

ContextRefreshedEvent在refresh方法的finishRefresh阶段触发,标志着所有Bean实例化完成、单例池填充完毕、容器完全可用。

监听方式两种:实现ApplicationListener接口,或用@EventListener注解。异步事件在方法上加@Async,需要先@EnableAsync。


【面试题】9. SpringBoot集成MyBatis时,@MapperScan和@Mapper注解有什么区别? ​

【标准答案】 @MapperScan是类注解,用在启动类或配置类上,批量扫描指定包下的所有接口,把它们注册成Mapper代理对象。比如@MapperScan("com.example.mapper"),扫描mapper包下所有接口。

@Mapper是接口注解,用在具体的Mapper接口上,标记这个接口需要被MyBatis处理。

区别:@MapperScan是批量注册,@Mapper是单独标记。两者可以共存,@MapperScan扫描的包不需要再写@Mapper,但如果Mapper接口在扫描包外,需要单独加@Mapper。

实际开发推荐用@MapperScan,配置一次就行,不用每个Mapper接口都写注解。

底层原理:@MapperScan通过@Import导入MapperScannerRegistrar,注册MapperScannerConfigurer这个BeanFactoryPostProcessor,扫描指定包,把接口注册成BeanDefinition,BeanClass是MapperFactoryBean,创建代理对象。


【面试题】10. SpringBoot的@Transactional注解在什么情况下会失效?怎么避免? ​

【标准答案】 失效场景主要有五种:

  1. 方法不是public,@Transactional只对public方法生效,因为CGLIB代理基于继承,private和protected方法无法被代理。

  2. 同一个类内部调用,事务方法A调用事务方法B,A没加事务,B的事务失效。因为调用不走代理,是this.方法调用。

  3. 异常被catch吞掉,默认只对RuntimeException回滚,如果catch住异常没抛出,事务不会回滚。可以指定rollbackFor = Exception.class。

  4. 数据库引擎不支持事务,比如MySQL的MyISAM。

  5. 传播行为设置错误,比如PROPAGATION_NOT_SUPPORTED以非事务方式运行。

解决方案:

  1. 方法必须是public
  2. 类内部调用要注入自己或用AopContext.currentProxy()
  3. 异常要抛出或指定rollbackFor
  4. 使用InnoDB引擎
  5. 默认传播行为REQUIRED,一般不用改

实际开发最容易踩坑的是类内部调用,要特别注意。