本轮 SpringBoot2核心功能面试题库(带答案)
【面试题】1. SpringBoot自动配置原理中,@EnableAutoConfiguration是如何实现自动装配的?
【标准答案】@EnableAutoConfiguration通过@Import导入AutoConfigurationImportSelector,这个Selector会读取META-INF/spring.factories或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,获取所有候选配置类的全限定名。然后根据条件注解(@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty等)进行过滤,最终只装配满足条件的配置类。整个过程是"约定优于配置"思想的体现,用户只需引入starter依赖,框架自动完成装配,降低了配置成本。
【面试题】2. SpringBoot中Bean的初始化回调有哪些方式?它们的执行顺序是什么?
【标准答案】有四种方式:@PostConstruct注解、InitializingBean接口的afterPropertiesSet()方法、自定义init-method配置、BeanPostProcessor的postProcessBeforeInitialization。执行顺序是:BeanPostProcessor的postProcessBeforeInitialization → @PostConstruct → InitializingBean.afterPropertiesSet() → 自定义init-method。面试中要强调@PostConstruct是最推荐的,因为它是JSR-250标准注解,与Spring解耦,代码简洁可读性强。同时要说明BeanPostProcessor是拦截器模式,可以对所有Bean进行统一处理,AOP、事务等核心功能都依赖它。
【面试题】3. SpringBoot的配置文件加载顺序和优先级是怎样的?
【标准答案】加载顺序从高到低优先级:命令行参数 → Java系统属性(System.getProperties())→ 操作系统环境变量 → RandomValuePropertySource随机值 → jar包外的application-{profile}.properties/yml → jar包内的application-{profile}.properties/yml → jar包外的application.properties/yml → jar包内的application.properties/yml → @PropertySource注解指定的属性文件 → 默认属性(SpringApplication.setDefaultProperties)。关键点:外部配置优先级高于内部,profile配置优先级高于默认配置,命令行参数优先级最高。实际项目中常用命令行参数覆盖生产环境配置,实现动态调整。
【面试题】4. SpringBoot中@Conditional系列条件注解有哪些?如何自定义条件注解?
【标准答案】核心注解包括:@ConditionalOnClass(类路径存在指定类)、@ConditionalOnMissingBean(容器中不存在指定Bean)、@ConditionalOnProperty(配置属性满足条件)、@ConditionalOnWebApplication(Web应用)、@ConditionalOnExpression(SpEL表达式满足条件)。自定义步骤:实现Condition接口重写matches()方法 → 创建自定义注解并用@Conditional标注 → 在配置类或Bean定义上使用自定义注解。实际应用场景:根据不同数据库类型动态切换DataSource、根据环境变量决定是否启用某些功能模块。
【面试题】5. SpringBoot AOP中,同一个切面类中多个通知方法的执行顺序是什么?不同切面类之间如何控制顺序?
【标准答案】同一个切面类中,不同通知类型有固定顺序:Around(前置部分)→ Before → 目标方法执行 → AfterReturning/AfterThrowing → After → Around(后置部分)。同一个切面类中有多个相同类型通知时,默认按方法定义顺序执行,也可用@Order指定顺序。不同切面类之间,通过@Order注解或实现Ordered接口控制,数值越小优先级越高。高优先级切面的Before先执行,After后执行(洋葱模型)。实际项目中要注意切面顺序对事务、日志等横切关注点的影响,比如事务切面通常优先级最高。
【面试题】6. SpringBoot事件机制中,ApplicationEvent与ApplicationListener如何使用?有哪些内置核心事件?
【标准答案】使用步骤:定义事件类继承ApplicationEvent → 定义监听器实现ApplicationListener或使用@EventListener注解 → 通过ApplicationContext.publishEvent()发布事件。内置核心事件按启动顺序:ApplicationStartingEvent(启动开始)→ ApplicationEnvironmentPreparedEvent(环境准备)→ ApplicationContextInitializedEvent(容器初始化)→ ApplicationPreparedEvent(容器准备完成)→ ContextRefreshedEvent(容器刷新完成)→ ApplicationStartedEvent(启动完成)→ ApplicationReadyEvent(就绪)→ ContextClosedEvent(容器关闭)。实际应用:监听ContextRefreshedEvent做初始化缓存加载、监听ApplicationReadyEvent做服务健康检查。
【面试题】7. SpringBoot嵌入式容器如何切换和调优?Tomcat与Undertow有什么区别?
【标准答案】切换容器:排除默认tomcat依赖 → 引入undertow或jetty依赖。配置调优关键参数:server.port端口、server.tomcat.max-threads最大工作线程、server.tomcat.accept-count等待队列长度、server.connection-timeout连接超时。Tomcat vs Undertow:Tomcat生态成熟、文档完善、性能稳定;Undertow轻量级、非阻塞IO、高并发性能更优、内存占用更小。生产环境选型:传统企业应用用Tomcat稳妥,高并发微服务场景考虑Undertow。面试要强调根据业务场景选型,不是盲目追新。
【面试题】8. SpringBoot事务管理中,@Transactional的传播行为和隔离级别如何理解?
【标准答案】传播行为(7种):REQUIRED(默认,有事务加入,无事务新建)、REQUIRES_NEW(总是新建事务,挂起当前事务)、SUPPORTS(有事务加入,无事务非事务执行)、NOT_SUPPORTED(非事务执行,挂起当前事务)、MANDATORY(必须在事务中调用,否则抛异常)、NEVER(不能在事务中调用,否则抛异常)、NESTED(嵌套事务,支持保存点)。隔离级别(5种):DEFAULT(数据库默认)、READ_UNCOMMITTED(读未提交)、READ_COMMITTED(读已提交)、REPEATABLE_READ(可重复读)、SERIALIZABLE(串行化)。面试要结合场景:REQUIRES_NEW用于独立日志记录、NESTED用于部分回滚、隔离级别要兼顾性能与一致性。
【面试题】9. SpringBoot缓存抽象中,@Cacheable/@CachePut/@CacheEvict的区别和使用场景是什么?
【标准答案】@Cacheable:查询时先查缓存,命中直接返回,未命中执行方法并缓存结果,适合读多写少的数据查询。@CachePut:每次都执行方法并将结果缓存,适合数据更新后强制刷新缓存场景。@CacheEvict:删除缓存,适合数据删除或修改后清理缓存。关键配置:value指定缓存名称、key指定缓存键(支持SpEL)、condition指定缓存条件。集成Redis:引入spring-boot-starter-data-redis → 配置Redis连接 → @EnableCaching启用缓存抽象。生产注意:缓存穿透(缓存空对象)、缓存击穿(加锁或永不过期)、缓存雪崩(随机过期时间)。
【面试题】10. SpringBoot Actuator端点有哪些?如何自定义HealthIndicator实现健康检查?
【标准答案】核心端点:/health(应用健康状态)、/info(应用信息)、/metrics(性能指标)、/env(环境变量)、/beans(Bean列表)、/mappings(URL映射)、/threaddump(线程快照)、/heapdump(堆内存快照)。安全配置:management.endpoints.web.exposure.include指定暴露端点、management.endpoint.health.show-details控制健康详情显示。自定义HealthIndicator:实现HealthIndicator接口重写health()方法 → 返回Health.up().withDetail("key","value").build()或Health.down().build() → SpringBoot自动发现并注册。实际应用:检查数据库连接、Redis连接、外部API可用性等,配合Prometheus+Grafana实现监控可视化。