中科创达 Java开发 二面 面经

1. 介绍一下Spring Boot的自动配置原理

Spring Boot的自动配置主要基于以下几个核心机制:

@SpringBootApplication注解:这是一个组合注解,包含了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan三个注解

@EnableAutoConfiguration的工作原理

  • 通过@Import注解导入AutoConfigurationImportSelector类
  • 该类会读取META-INF/spring.factories文件中的配置类
  • 加载所有候选的自动配置类

条件注解机制

  • 使用@ConditionalOnClass判断类路径下是否存在某个类
  • 使用@ConditionalOnBean判断容器中是否存在某个Bean
  • 使用@ConditionalOnProperty判断配置文件中是否有某个属性
  • 只有满足条件的配置类才会生效

配置优先级:用户自定义的配置优先级高于自动配置,可以通过application.properties覆盖默认配置

实际应用:比如引入spring-boot-starter-web依赖后,会自动配置Tomcat、DispatcherServlet等组件,无需手动配置

2. 说说你对Redis的理解,以及常见的应用场景

Redis是一个基于内存的高性能键值数据库,我从以下几个方面理解:

数据结构丰富

  • String:最基本的类型,可以存储字符串、数字
  • Hash:适合存储对象
  • List:有序列表,可以实现队列和栈
  • Set:无序集合,支持交并差运算
  • ZSet:有序集合,可以实现排行榜

持久化机制

  • RDB:定期生成快照,恢复速度快但可能丢失数据
  • AOF:记录每个写操作,数据更安全但文件较大
  • 可以同时使用两种方式

常见应用场景

  • 缓存:减轻数据库压力,提高响应速度
  • 分布式锁:使用SETNX实现
  • 消息队列:使用List或Stream实现
  • 排行榜:使用ZSet的score排序
  • 计数器:使用INCR原子操作
  • Session共享:分布式系统中存储用户会话

缓存问题及解决方案

  • 缓存穿透:查询不存在的数据,解决方法是布隆过滤器或缓存空值
  • 缓存击穿:热点key过期,解决方法是互斥锁或永不过期
  • 缓存雪崩:大量key同时过期,解决方法是过期时间加随机值

3. 讲一下MySQL的事务隔离级别,以及会产生什么问题

MySQL的事务隔离级别从低到高分为四种:

读未提交(Read Uncommitted)

  • 最低的隔离级别
  • 会产生脏读问题:事务A读到了事务B未提交的数据
  • 基本不使用

读已提交(Read Committed)

  • 只能读取已提交的数据
  • 解决了脏读问题
  • 会产生不可重复读:事务A两次读取同一数据结果不同,因为事务B在中间修改并提交了
  • Oracle默认级别

可重复读(Repeatable Read)

  • 保证在同一事务中多次读取同一数据结果一致
  • 解决了不可重复读问题
  • 会产生幻读:事务A查询某个范围的数据,事务B插入了新数据,事务A再次查询发现多了数据
  • MySQL默认级别,通过MVCC和间隙锁解决了幻读

串行化(Serializable)

  • 最高的隔离级别
  • 强制事务串行执行
  • 解决了所有并发问题
  • 性能最差,很少使用

MySQL的实现机制

  • 使用MVCC(多版本并发控制)实现读已提交和可重复读
  • 每行数据有隐藏的版本号字段
  • 读取时根据版本号判断数据可见性
  • 避免了加锁,提高了并发性能

4. 分布式系统中如何保证接口的幂等性?

接口幂等性是指多次调用产生的结果与单次调用一致,实现方式有:

数据库唯一索引

  • 在数据库表中建立唯一索引
  • 重复插入会抛出异常
  • 适用于插入操作

Token机制

  • 客户端先请求获取Token
  • 提交时携带Token
  • 服务端验证Token并删除
  • 重复提交因为Token已被删除而失败
  • 适用于表单提交

分布式锁

  • 使用Redis的SETNX或Redisson实现
  • 获取锁成功才执行业务
  • 执行完释放锁
  • 适用于高并发场景

状态机

  • 通过状态流转控制
  • 比如订单状态:待支付→已支付→已发货
  • 已支付状态不能再次支付
  • 适用于有明确状态流转的业务

乐观锁

  • 使用版本号version字段
  • 更新时判断version是否一致
  • 不一致说明数据已被修改
  • 适用于更新操作

去重表

  • 建立专门的去重表记录请求ID
  • 每次请求先查询是否存在
  • 存在则直接返回
  • 适用于需要记录请求历史的场景

5. 说说你对微服务架构的理解,以及遇到过什么问题

微服务架构是将单体应用拆分成多个小服务的架构模式:

核心特点

  • 服务独立部署:每个服务可以独立发布
  • 技术栈灵活:不同服务可以用不同技术
  • 数据库独立:每个服务有自己的数据库
  • 按业务拆分:根据业务领域划分服务

常用组件

  • 注册中心:Nacos、Eureka,实现服务注册与发现
  • 配置中心:Nacos、Apollo,统一管理配置
  • 网关:Gateway、Zuul,统一入口和路由
  • 负载均衡:Ribbon、LoadBalancer
  • 熔断降级:Sentinel、Hystrix
  • 链路追踪:Skywalking、Zipkin

遇到的问题及解决方案

  • 分布式事务:使用Seata实现AT模式或TCC模式,或者采用最终一致性方案
  • 服务雪崩:通过Sentinel设置熔断降级规则,快速失败保护系统
  • 数据一致性:使用消息队列实现最终一致性,或者使用分布式锁
  • 接口调用复杂:使用OpenFeign简化HTTP调用,声明式调用
  • 服务拆分粒度:遵循单一职责原则,不能拆得过细也不能过粗

优缺点

  • 优点:独立部署、技

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务