Skip to content

SpringBoot2核心功能面试题库 ​

生成时间:2026-05-22 23:00


【面试题】1. SpringBoot自动配置的"约定优于配置"体现在哪些方面?请结合@Conditional系列注解说明。 ​

【标准答案】SpringBoot自动配置的核心思想就是"约定优于配置",体现为三点:第一,classpath下有某个类就自动配置对应的Bean(@ConditionalOnClass),比如引入了tomcat-embed-core就自动配嵌入式Tomcat;第二,用户没有自定义Bean就用默认的(@ConditionalOnMissingBean),比如你没有配DataSource就给你搓一个HikariCP的;第三,配置属性有值才生效(@ConditionalOnProperty),比如spring.cache.type=redis才激活Redis缓存配置。@Conditional系列是整个自动配置的开关引擎,常见的还有@ConditionalOnWebApplication、@ConditionalOnExpression等。面试时要强调:这些条件注解不是SpringBoot新发明的,而是基于Spring 4的@Conditional机制,SpringBoot只是扩展了丰富的具体实现。

【面试题】2. SpringBoot配置文件的加载优先级是怎样的?外部化配置有哪些来源? ​

【标准答案】SpringBoot外部化配置优先级从高到低:1)命令行参数;2)JNDI属性;3)Java系统属性(System.getProperties());4)操作系统环境变量;5)jar包外application-{profile}.yml;6)jar包内application-{profile}.yml;7)jar包外application.yml;8)jar包内application.yml;9)@PropertySource标注的属性源;10)SpringApplication.setDefaultProperties设置的默认属性。关键记忆点:命令行参数最高,jar包外优先于jar包内,profile专属优先于默认。实际开发中最常用的覆盖方式:启动命令加--server.port=8081,或者jar同级目录放application.yml覆盖内部配置。

【面试题】3. @ConfigurationProperties和@Value有什么区别?什么场景用哪个? ​

【标准答案】核心区别三点:第一,@ConfigurationProperties是批量绑定,把整个前缀下的属性映射到一个Bean;@Value是逐个注入,一个注解只绑定一个值。第二,@ConfigurationProperties支持松散绑定(my-prop能匹配myProp、my_prop),@Value必须精确匹配。第三,@ConfigurationProperties配合@Validated支持JSR303校验,@Value不支持。使用场景:属性多、有层级结构、需要校验的用@ConfigurationProperties(比如数据源配置类);就取一两个简单值用@Value更轻量(比如@Value("${custom.flag:false}"))。面试加分点:@ConfigurationProperties标注的类必须是Spring管理的Bean,通常配合@EnableConfigurationProperties或@Component使用。

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

【标准答案】BeanFactory是Spring最底层的容器接口,只提供Bean的获取和基础依赖注入;ApplicationContext是BeanFactory的子接口,在BeanFactory基础上扩展了国际化、事件发布、资源加载、AOP集成等企业级功能。关键区别:BeanFactory是懒加载,首次getBean时才创建;ApplicationContext默认预加载,容器启动时就创建所有单例Bean。SpringBoot用的是ApplicationContext的实现——AnnotationConfigServletWebServerApplicationContext。面试时补充一点:实际开发中基本不会直接用BeanFactory,ApplicationContext才是主流,BeanFactory更多是框架内部的设计分层的产物。

【面试题】5. BeanPostProcessor和BeanFactoryPostProcessor的区别是什么?分别在Bean生命周期的哪个阶段执行? ​

【标准答案】BeanFactoryPostProcessor在BeanDefinition注册之后、Bean实例化之前执行,用来修改Bean的定义信息,比如修改属性值、改scope。典型应用:PropertyPlaceholderConfigurer解析占位符替换属性值。BeanPostProcessor在Bean实例化之后执行,分before和after两个回调,用来对Bean实例做包装或增强。典型应用:AutowiredAnnotationBeanPostProcessor处理@Autowired注入,CommonAnnotationBeanPostProcessor处理@PostConstruct。执行顺序:BeanFactoryPostProcessor → Bean实例化 → BeanPostProcessor.before → 初始化回调 → BeanPostProcessor.after。面试时一定要说清:前者改定义,后者改实例,时机完全不同。

【面试题】6. SpringBoot中AOP的代理方式有哪些?什么情况用JDK动态代理,什么情况用CGLIB? ​

【标准答案】两种代理方式:JDK动态代理基于接口,通过java.lang.reflect.Proxy生成代理类,目标类必须实现接口;CGLIB基于继承,通过字节码技术生成目标类的子类,目标类不能是final类、方法不能是final。SpringBoot 2.x默认规则:目标类实现了接口也优先使用CGLIB(spring.aop.proxy-target-class默认true,SpringBoot 2.x改了默认值)。如果一定要用JDK代理,设spring.aop.proxy-target-class=false。面试要点:为什么SpringBoot 2.x改默认值?因为JDK代理只能代理接口方法,如果目标类有自己的public方法(不在接口中),JDK代理调不到,容易踩坑。CGLIB更安全。

【面试题】7. SpringBoot的事件机制是怎么工作的?有哪些核心内置事件?自定义事件怎么发? ​

【标准答案】SpringBoot事件机制基于Spring的ApplicationEvent和ApplicationListener体系。核心内置事件按触发顺序:ApplicationStartingEvent → ApplicationEnvironmentPreparedEvent → ApplicationContextInitializedEvent → ApplicationPreparedEvent → ContextRefreshedEvent → ContextStartedEvent → ContextReadyEvent → ContextClosedEvent。自定义事件三步走:1)定义事件类继承ApplicationEvent;2)发布事件,注入ApplicationEventPublisher调用publishEvent();3)监听事件,实现ApplicationListener或用@EventListener注解。异步事件在@EventListener上加@Async即可。面试关键点:ContextRefreshedEvent是最常用的,容器刷新完成时触发,很多组件在这个时机做初始化。

【面试题】8. @Transactional的传播行为有哪些?实际开发中最常用的是哪几个?什么场景需要注意? ​

【标准答案】7种传播行为:REQUIRED(默认,有事务加入,没有就新建)、SUPPORTS(有事务加入,没有非事务执行)、MANDATORY(必须在事务中,否则抛异常)、REQUIRES_NEW(始终新建事务,挂起当前事务)、NOT_SUPPORTED(非事务执行,挂起当前事务)、NEVER(非事务执行,存在事务则抛异常)、NESTED(有事务则嵌套,没有就新建)。最常用的是REQUIRED和REQUIRES_NEW。REQUIRED适用于大多数业务方法;REQUIRES_NEW用于独立事务场景,比如日志记录,不想因为业务回滚而丢失日志。NESTED是嵌套事务,保存点机制,外层回滚内层也回滚,内层回滚不影响外层。踩坑点:同类中方法A调方法B,B的@Transactional不生效,因为绕过了代理对象,这是self-invocation问题。

【面试题】9. SpringBoot集成Redis缓存,@Cacheable/@CachePut/@CacheEvict分别什么作用?缓存穿透怎么防? ​

【标准答案】三个注解分工明确:@Cacheable——查缓存,有直接返回,没有执行方法后存缓存;@CachePut——不查缓存,始终执行方法,然后把结果存缓存,用于更新;@CacheEvict——删缓存,用于删除操作后清除对应缓存项。防缓存穿透三种方案:1)缓存空值,查询为null也缓存,设短过期时间;2)布隆过滤器,在缓存前加一层布隆过滤,不存在的key直接拦截;3)接口层校验参数合法性,非法请求直接拒绝。实际推荐:缓存空值+布隆过滤器组合使用。另外,@Cacheable的key属性要用SpEL表达式精确定义,避免key冲突,比如@Cacheable(value="user", key="#id")。

【面试题】10. SpringBoot的spring-boot-maven-plugin打包和普通maven打包有什么区别?分层JAR是什么? ​

【标准答案】普通maven打包只把编译后的class文件和资源打进jar,不包含依赖jar,运行时需要外部classpath。spring-boot-maven-plugin做了三件事:1)把所有依赖jar包打进fat jar的BOOT-INF/lib目录;2)项目class放进BOOT-INF/classes;3)设置Main-Class为JarLauncher,它负责加载lib下的依赖再启动应用。分层JAR(Layered JAR)是SpringBoot 2.3+的特性,把jar按变更频率分成四层:dependencies(第三方依赖,变最少)→ spring-boot-loader → snapshot-dependencies → application(项目代码,变更最多)。Docker构建时每层对应一个镜像层,代码变了只重建application层,不动依赖层,大幅加快构建速度。启用方式:spring-boot-maven-plugin配置<layout>ZIP</layout>或<layers><enabled>true</enabled></layers>,配合dockerfile的分层COPY指令使用。