大厂Java面试深度解析:Spring事务与MySQL优化实战

📅 2026/8/22 5:00:10
大厂Java面试深度解析:Spring事务与MySQL优化实战
1. 大厂Java面试的生存法则去年面了6家大厂最终拿下3个offer。我发现大厂Java面试早已不是简单的八股文背诵而是对技术深度和实战能力的全方位考察。面试官更看重候选人能否将理论知识应用到实际业务场景中特别是在高并发、分布式系统设计方面的实战经验。以Spring事务管理为例很多候选人能背出传播机制和隔离级别但当被问到你们系统如何处理分布式事务时往往就露怯了。我在美团二面时面试官直接让我在白板上画出秒杀系统的完整事务方案这需要真正做过相关优化才能答得上来。2. 技术栈深度解析2.1 Spring框架核心机制2.1.1 循环依赖的破局之道大厂面试必问Spring的循环依赖解决机制。以A依赖BB又依赖A的典型场景为例Spring通过三级缓存巧妙解决// 三级缓存定义 public class DefaultSingletonBeanRegistry { // 一级缓存完整Bean private final MapString, Object singletonObjects new ConcurrentHashMap(256); // 二级缓存早期引用 private final MapString, Object earlySingletonObjects new ConcurrentHashMap(16); // 三级缓存对象工厂 private final MapString, ObjectFactory? singletonFactories new HashMap(16); }解决流程分五步创建A实例放入三级缓存填充A属性时发现依赖B创建B实例填充属性时又需要A从三级缓存获取A的早期引用完成B初始化后回溯完成A初始化注意构造器注入无法解决循环依赖必须使用setter注入2.1.2 事务失效的七大陷阱我在阿里三面时被问到事务失效场景整理出这些实际踩过的坑异常类型不匹配默认只回滚RuntimeException// 必须指定rollbackFor Transactional(rollbackFor Exception.class) public void transfer() throws BusinessException {}内部调用this调用绕过代理public class OrderService { public void createOrder() { this.updateStatus(); // 事务失效 } Transactional public void updateStatus() {} }数据库引擎不支持MyISAM不支持事务传播机制误用PROPAGATION_NOT_SUPPORTED会挂起当前事务异常被捕获catch后未重新抛出非public方法动态代理无法生效多数据源未配置需指定事务管理器2.2 MySQL深度优化2.2.1 索引失效的隐蔽场景即使建立了索引这些情况仍会导致全表扫描使用!或操作符对索引列进行运算隐式类型转换最左前缀原则违反使用%开头的LIKE查询-- 反面案例 SELECT * FROM users WHERE DATE(create_time) 2023-01-01; -- 优化方案 SELECT * FROM users WHERE create_time BETWEEN 2023-01-01 00:00:00 AND 2023-01-01 23:59:59;2.2.2 死锁分析与解决某次压测时出现的死锁日志LATEST DETECTED DEADLOCK ------------------------ 2023-03-15 14:23:56 *** (1) TRANSACTION: TRANSACTION 1821, ACTIVE 0 sec starting index read mysql tables in use 1, locked 1 LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 17, OS thread handle 139887555282688, query id 1234 localhost root updating UPDATE account SET balance balance - 100 WHERE id 1 *** (2) TRANSACTION: TRANSACTION 1822, ACTIVE 0 sec starting index read mysql tables in use 1, locked 1 2 lock struct(s), heap size 1136, 1 row lock(s) MySQL thread id 18, OS thread handle 139887554959104, query id 1235 localhost root updating UPDATE account SET balance balance - 50 WHERE id 2解决方案统一SQL执行顺序减小事务粒度使用乐观锁替代设置锁超时时间2.3 SpringBoot自动配置原理2.3.1 启动流程解密SpringBoot启动时的关键步骤加载META-INF/spring.factories2.7版本是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports过滤符合条件的自动配置类执行自动配置类的Bean方法// 自动配置条件判断示例 Configuration ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) EnableConfigurationProperties(DataSourceProperties.class) public class DataSourceAutoConfiguration { Bean ConditionalOnMissingBean public DataSource dataSource() { // 自动配置数据源 } }2.3.2 自定义Starter开发开发监控组件的Starter步骤创建autoconfigure模块添加配置类Configuration AutoConfigureAfter(DataSourceAutoConfiguration.class) ConditionalOnProperty(prefix monitor, name enabled, havingValue true) public class MonitorAutoConfiguration { Bean public MonitorService monitorService() { return new MonitorServiceImpl(); } }配置META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.importscom.example.MonitorAutoConfiguration添加spring.factories兼容旧版org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.MonitorAutoConfiguration3. 面试实战技巧3.1 系统设计题应答策略面对设计一个秒杀系统这类问题我的应答框架明确需求确认QPS、库存量、一致性要求分层设计接入层限流RedisLua服务层缓存预热、库存分段数据层乐观锁、异步落库容灾方案降级策略、热点key处理// 分段库存示例 public class SegmentInventoryService { private MapInteger, AtomicInteger segments; public boolean deductStock(Long itemId) { int segment hash(itemId) % SEGMENT_COUNT; return segments.get(segment) .decrementAndGet() 0; } }3.2 项目难点剖析方法用STAR法则讲述项目难点Situation日订单量突破50万原有系统响应超时Task需要在2周内将平均响应时间降至200ms内Action引入二级缓存CaffeineRedis优化SQL消除N1查询异步化非核心流程ResultTP99从1200ms降至150ms3.3 编码题常见陷阱二叉树层序遍历的坑点// 易错点忘记处理空树 public ListListInteger levelOrder(TreeNode root) { ListListInteger res new ArrayList(); if (root null) return res; // 关键检查 QueueTreeNode queue new LinkedList(); queue.offer(root); while (!queue.isEmpty()) { int levelSize queue.size(); ListInteger level new ArrayList(); for (int i 0; i levelSize; i) { TreeNode node queue.poll(); level.add(node.val); if (node.left ! null) queue.offer(node.left); if (node.right ! null) queue.offer(node.right); } res.add(level); } return res; }4. 高频问题深度解析4.1 Spring事务传播机制实战七种传播行为的实际应用场景传播行为场景示例注意事项REQUIRED订单创建库存扣减默认选择REQUIRES_NEW操作日志记录需要独立事务NESTED批量处理子任务只适用于JDBCNOT_SUPPORTED发送短信通知挂起当前事务// 嵌套事务示例 Transactional public void batchProcess(ListItem items) { for (Item item : items) { try { processItem(item); } catch (Exception e) { // 只回滚当前item处理 TransactionAspectSupport.currentTransactionStatus() .setRollbackOnly(); } } } Transactional(propagation Propagation.NESTED) public void processItem(Item item) { // 业务处理 }4.2 JVM调优实战案例某次FullGC频繁的排查过程现象每2小时发生一次FullGC排查jstat -gcutil查看内存分布jmap -histo分析对象分布发现缓存层未设置TTL导致老年代堆积解决添加Redis缓存过期时间调整JVM参数-XX:UseG1GC -XX:MaxGCPauseMillis200 -XX:InitiatingHeapOccupancyPercent454.3 Redis缓存穿透解决方案三种防御方案对比空值缓存public Product getProduct(Long id) { String key product: id; String value redis.get(key); if (NULL.equals(value)) { return null; } if (value null) { Product product db.get(id); redis.setex(key, product null ? NULL : product, 300); return product; } return deserialize(value); }布隆过滤器// 初始化布隆过滤器 BloomFilter.create( Funnels.longFunnel(), 1000000, 0.01); // 查询前先检查 if (!bloomFilter.mightContain(id)) { return null; }互斥锁public Product getProductWithLock(Long id) { String lockKey lock:product: id; try { if (redis.setnx(lockKey, 1, 10, TimeUnit.SECONDS)) { Product product db.get(id); redis.setex(product: id, product, 3600); return product; } Thread.sleep(50); return getProductWithLock(id); } finally { redis.delete(lockKey); } }5. 面试后的关键动作复盘记录立即记录被问倒的问题技术补漏针对薄弱点做专项突破感谢信24小时内发送个性化感谢邮件持续跟进适当询问面试结果我在面试腾讯时整理的复盘表问题类型问题描述我的回答改进方案算法题链表排序用了额外空间练习原地归并系统设计分布式ID生成只说了UUID学习Snowflake项目细节缓存一致性回答不完整研究双删策略最后给准备大厂面试的同学三个建议保持每周至少2次模拟面试建立自己的技术知识图谱最重要的是——把每次面试都当作一次技术交流的机会而非考试。