《Java面试85题图解版(二)》进阶深化中篇:Spring核心 + 数据库进阶

📘 《Java面试85题图解版(二)》进阶深化中篇:Spring核心 + 数据库进阶

阅读提示 :这是"图解+比喻+一句话总结"面试题库第二篇的进阶深化中篇 ,覆盖Spring核心与Spring Boot(9题)和数据库进阶(8题)共17道高频面试题。每道题仍然是四层结构------结构图 → 场景比喻 → 关键对比表 → 一句话总结


三、Spring 核心与 Spring Boot(第44-52题)

📌 第44题:Spring IoC 与 DI

一图看清

复制代码
传统方式(控制正转)         IoC方式(控制反转)
应用程序主动 new 对象       容器创建对象并注入
"我去拿"                    "我给你"

比喻记忆DIY组装 vs 品牌整机

  • 传统:自己跑电子城买CPU、主板、内存,自己组装。得知道每样配件的型号、接口。
  • IoC:直接买品牌机,描述需求"我要打游戏"。工厂帮你采购所有零件,组装好,插上电,送到桌上。
  • DI:电脑送到时显卡、内存已插好,系统已装好------你关心整体功能,不关心零件间怎么连线。

💡 一句话总结IoC是把控制权交给容器,DI是容器把装配好的对象推给你。


📌 第45题:Spring Bean 生命周期

一图看清

复制代码
实例化 → 属性注入(@Autowired) → 各种Aware接口回调
→ BeanPostProcessor前置处理
→ @PostConstruct初始化方法
→ InitializingBean.afterPropertiesSet()
→ 自定义init-method
→ BeanPostProcessor后置处理(AOP代理在此发生)
→ 使用
→ @PreDestroy → DisposableBean.destroy() → 自定义destroy-method

比喻记忆新员工入职到离职

  • 实例化:签劳动合同。
  • 属性注入:配发电脑、工牌(依赖注入)。
  • Aware回调:知道自己工号(BeanNameAware)、所属部门(BeanFactoryAware)。
  • @PostConstruct:安好自己工位,开始工作。
  • AOP代理:给他配个助理(代理对象),对外由助理处理。
  • @PreDestroy:离职前交接工作。

💡 一句话总结Spring Bean从实例化到销毁经历十几步,AOP代理在后置处理器环节生成。


📌 第46题:Spring AOP 底层原理

一图看清

复制代码
JDK动态代理:基于接口,Proxy.newProxyInstance生成代理类
CGLIB代理:基于继承,生成目标类的子类

Spring Boot 1.x:有接口用JDK,无接口用CGLIB
Spring Boot 2.x起:默认CGLIB(即使有接口也用它)

比喻记忆两种明星经纪模式

  • JDK代理:明星只按合同走穴(接口),经纪人代理合同上的所有服务。
  • CGLIB代理:经纪人直接扮演明星的替身(继承明星类),连合同上没写的行程都接管了。

💡 一句话总结有接口用JDK,无接口用CGLIB;Boot 2.x起默认CGLIB,final类无法代理。


📌 第47题:Spring 循环依赖与三级缓存

一图看清

复制代码
三级缓存:
  一级 singletonObjects:完全初始化好的Bean(成品)
  二级 earlySingletonObjects:早期半成品引用
  三级 singletonFactories:对象工厂,可生成代理

A实例化 → 三级缓存存A工厂 → 填充B属性,发现需要B
→ B实例化 → 三级缓存存B工厂 → 填充A属性,从三级获取A早期引用
→ B完成 → 放入一级缓存 → A获得完整B → A完成 → 一级缓存

比喻记忆情侣杯制作

  • 制作A杯:捏出A杯泥胚,模具放入三级。要在A上印B头像,B还没做。
  • 制作B杯:捏B杯,印A头像时从三级取出A的模具。B烧制完成,放入成品柜(一级)。
  • 回到A杯:印上已完成B的头像,A烧制完成。

⚠️ 构造器注入无法解决:杯胚还没捏出来就要对方头像,不可能。

💡 一句话总结三级缓存解单例Setter循环依赖,构造器注入无解。


📌 第48题:Spring Boot 自动装配原理

一图看清

复制代码
@SpringBootApplication
 → @EnableAutoConfiguration
   → @Import(AutoConfigurationImportSelector)
     → 读取 META-INF/spring/...AutoConfiguration.imports
       → 加载所有候选配置类
         → @Conditional条件过滤(@ConditionalOnClass、@ConditionalOnMissingBean等)
           → 条件满足则创建Bean

比喻记忆商场智能供货系统

  • AutoConfiguration.imports:全球所有能供货的品牌清单。
  • AutoConfigurationImportSelector:供应链经理,挨个打电话看品牌是否还活着(classpath有无)。
  • @ConditionalOnMissingBean:你已经自己进了耐克鞋?那我就不供了,避免摆两家打架。
  • 最终效果:空货架自动摆上默认商品,开箱即用。你自己进的货(自定义Bean)优先。

💡 一句话总结读全量候选配置→条件过滤→只装你缺的,用户自定义覆盖默认。


📌 第49题:@SpringBootApplication 三个核心注解

一图看清

复制代码
@SpringBootApplication =
  @SpringBootConfiguration(本质是@Configuration,标记配置类)
  + @EnableAutoConfiguration(自动装配)
  + @ComponentScan(组件扫描,默认扫描主类所在包及子包)

比喻记忆三合一办公套件

  • @SpringBootConfiguration:挂牌"此房间是配置办公室"。
  • @EnableAutoConfiguration:自动雇齐前台、保洁、网管。
  • @ComponentScan:扫描全公司,看谁挂着工牌(@Component、@Service、@Controller等)。

💡 一句话总结一个注解三功能:配置类+自动装配+组件扫描。


📌 第50题:@Transactional 失效场景

一图看清

复制代码
生效前提:public方法 + 经过Spring代理调用 + 异常正确抛出

常见失效:
  同类内部调用(this.method()不走代理)
  方法非public(private/protected)
  异常被catch吞掉没抛出去
  rollbackFor未指定,只回滚RuntimeException和Error,受检异常不回滚
  数据库引擎不支持事务(MyISAM)
  多线程拿不到同一个事务

比喻记忆酒店无线门卡

  • 走过代理:必须刷门卡过闸机(AOP代理),系统才记录进出。
  • 同类调用:在房间里直接把东西递给朋友,不经过闸机,酒店系统不知道。
  • catch吞异常:前台手动掩盖了出错的记录,财务部不知道自然不会退款。
  • 受检异常:酒店只在"房费付不了"时自动退款(RuntimeException)。忘带身份证这种小问题不管,除非提前说"任何问题都退款"(rollbackFor = Exception.class)。

💡 一句话总结事务生效三要素:public方法、走过代理、异常正确抛出。


📌 第51题:Spring MVC 请求处理流程

一图看清

复制代码
请求 → DispatcherServlet(中央调度)
→ HandlerMapping(找对应的Controller)
→ HandlerAdapter(执行Handler)
→ Controller执行业务 → 返回ModelAndView 或 @ResponseBody
→ ViewResolver解析视图 / HttpMessageConverter写JSON
→ 响应返回

比喻记忆电影院放映流程

  • DispatcherServlet:售票大厅前台,所有观众先到前台。
  • HandlerMapping:排片表,查"《流浪地球》在几号厅"。
  • HandlerAdapter:放映员,按下播放键(调用Controller方法)。
  • Controller:电影正片(执行业务逻辑)。
  • ViewResolver:画面投射到正确银幕,或给手机用户直接发链接(@ResponseBody返回JSON)。
  • 拦截器:检票员,入场前查票,散场后检查卫生。

💡 一句话总结请求经DispatcherServlet统一调度,Mapping找Handler,Adapter执行,ViewResolver渲染。


📌 第52题:Spring Boot Starter 自定义

一图看清

复制代码
1. 创建autoconfigure模块 → 写自动配置类 + @Conditional条件
2. 在META-INF/spring/...AutoConfiguration.imports声明配置类全限定名
3. 创建starter模块 → pom引入autoconfigure和相关三方依赖
4. 可通过@EnableConfigurationProperties绑定配置属性

比喻记忆乐高套装

  • Autoconfigure模块:拼装说明书,告诉你一套零件怎么拼成功能。
  • Starter模块:乐高套装盒子,包含说明书+全部零件。
  • 你只要引入一个Starter依赖,开箱就能拼出功能模块(如数据源、Redis连接)。

💡 一句话总结Starter = 自动配置类 + 依赖打包,实现即插即用。


四、数据库进阶(第53-60题)

📌 第53题:MySQL 三日志体系

一图看清

复制代码
redo log(InnoDB引擎层):物理日志,记录页修改,崩溃恢复,循环写
undo log(InnoDB引擎层):逻辑日志,记录修改前版本,事务回滚+MVCC
binlog(Server层):逻辑日志,记录SQL语句变更,主从复制+数据恢复

两阶段提交:
1. redo log prepare → 2. 写binlog → 3. redo log commit
保证redo和binlog一致性

比喻记忆财务三重备份

  • redo log:便签纸,改账本前先记"将第3页第5行改成100"。停电后按便签重做。
  • undo log:改前复印旧页,老板说撤销就拿复印件还原。别人读旧版也看复印件(MVCC)。
  • binlog:审计邮件,每次改完发一封标准格式邮件给审计部(从库),永久存档。

两阶段提交:财务写完便签不擦(prepare),发完审计邮件(写binlog),才在便签打勾(commit)。

💡 一句话总结redo保崩溃恢复,undo保回滚,binlog保复制,两阶段提交保一致。


📌 第54题:PostgreSQL WAL vs MySQL 日志体系

一图看清

复制代码
PG WAL:类似 redo log + binlog 综合体
  崩溃恢复 ✅  流复制 ✅  无独立undo log(旧版本留数据页)

MySQL:redo(InnoDB)+ binlog(Server)分开管理
  有独立undo log,在回滚段

比喻记忆两种档案管理

  • PG WAL:一本总账既记录修改也用于传阅副本(流复制),老版本直接留在账面,定期VACUUM清理。
  • MySQL:便签(redo)做恢复 + 审计邮件(binlog)做复制,老版本留底单(undo),purge线程清理。

💡 一句话总结PG用WAL一统恢复和复制,MySQL用redo+binlog分工协作。


📌 第55题:MySQL 索引失效八大场景

一图看清

复制代码
失效场景:
  LIKE '%xxx'(左模糊)
  WHERE YEAR(time)=2025(函数包裹列)
  WHERE phone=1380000 但phone是varchar(隐式类型转换)
  WHERE b=2 联合索引(a,b)跳过最左列
  WHERE a!=1 或 NOT IN(负向查询)
  WHERE a=1 OR b=2(OR部分无索引)
  数据量小,全表扫描更快
  统计信息不准,优化器误判

比喻记忆字典查字

  • 左模糊:找所有含"明"字的词,拼音排序是按开头字母排的,不知道开头只能一页页翻。
  • 函数包裹:找"笔画数是12的字",字典按拼音排不是按笔画,得先数完所有字再找。
  • 隐式类型转换:你给数字10查"笔画等于10",但索引是按文字类别分的,倒过来全错。
  • 违背最左前缀:联合索引像"北京→海淀→中关村"地址,跳过北京直接查"海淀"无法快速定位。

💡 一句话总结索引怕左模糊、函数套列、类型转换、跳过最左列、负向和OR没索引。


📌 第56题:PostgreSQL 高级索引类型

一图看清

复制代码
B+Tree:通用等值/范围查询
GIN:倒排索引,JSONB包含、数组包含、全文检索
GiST:通用可扩展,空间几何、范围类型、全文
BRIN:块范围索引,极小体积,适合数十亿行的顺序大表
SP-GiST:空间分区,如IP地址

比喻记忆仓库四种找货方式

  • B+Tree:常规货架,按编号找,范围查询顺着走。
  • GIN:属性倒排本,"红色M码A字裙"查三个清单取交集。
  • GiST:仓库平面图,画圆规量距离,测几何形状。
  • BRIN:集装箱范围标签,每箱只写"这箱是1月1号到3号的货"。找1月5号的跳过前面20个箱。

💡 一句话总结B+Tree普适,GIN善包含查询,GiST善空间,BRIN极小体积处理超大表。


📌 第57题:MySQL 主从复制 vs PG 流复制

一图看清

复制代码
MySQL:主写binlog → 从I/O线程拉取→写入relay log → SQL线程重放
PG:主WAL流持续发送 → 备库实时重放WAL,物理同步
PG10+逻辑复制:发布/订阅模型,表级复制,类似MySQL binlog

比喻记忆两种远程教学

  • MySQL:老师讲课录像(binlog)发给分校,分校老师看录像回放(重放)。
  • PG流复制:实时直播(WAL流),分校同步播放。
  • PG逻辑复制:只转发指定科目的课程录像。

💡 一句话总结MySQL基于binlog逻辑复制,PG基于WAL物理流复制,PG10+亦支持逻辑复制。


📌 第58题:doublewrite vs full_page_writes

一图看清

复制代码
部分写失效:16KB页写到一半断电,页损坏无法恢复

MySQL doublewrite:脏页先顺序写共享表空间的doublewrite buffer,再写数据文件
PG full_page_writes:checkpoint后首次修改,全页镜像写入WAL

目的相同:防止页断裂

比喻记忆快递防碎包装

  • MySQL doublewrite:先给完整打包好的杯子拍照存保险柜(doublewrite buffer)。运输碎了就拿照片恢复。
  • PG full_page_writes:不在别处存备份,但在发货清单(WAL)上画了杯子完整包装图。碎了查清单找回。

💡 一句话总结两者都防页断裂,MySQL额外存副本,PG把完整页嵌入WAL。


📌 第59题:MySQL vs PG 并发控制差异

一图看清

复制代码
MySQL InnoDB:锁索引记录,Record Lock + Gap Lock + Next-Key Lock防幻读
PG:元组标记xmin/xmax,更新不阻塞读,锁信息存在tuple中,无专门锁内存区

比喻记忆两种餐厅管理

  • MySQL:预约制,订位就锁住餐桌,别人不能坐(主动加锁)。
  • PG:自助模式,坐下后在桌上放"已占"牌(标记元组)。别人能看到空余座位但不能占你的。你走了得清理牌子(VACUUM)。

💡 一句话总结MySQL主动加锁防冲突,PG被动标记靠清理。


📌 第60题:MySQL分库分表 vs PG原生分区

一图看清

复制代码
MySQL:依赖中间件(ShardingSphere, MyCat),应用层处理路由
PG:原生声明式分区(范围/列表/哈希),自动路由,分区裁剪

比喻记忆手动分柜 vs 智能仓储

  • MySQL中间件:几个独立小仓库,你拿单子自己判断去哪个仓库找。
  • PG原生分区:一个智能大仓库,系统按标签自动把货分到对应区域。找货时告诉你哪些区域不用看(分区裁剪)。

💡 一句话总结MySQL靠中间件手工分片,PG原生分区透明路由+自动裁剪。


📌 下篇预告

本篇(中篇)我们深入了 Spring核心(IoC、AOP、循环依赖、事务失效等)数据库进阶(MySQL与PG日志、索引、复制、分片等),共17道面试必考题。

下一篇(进阶深化下篇) 将专注于 Redis缓存,涵盖8道高频题:为什么快、数据类型、持久化、过期淘汰、穿透击穿雪崩、分布式锁、哨兵与集群、6.0多线程模型。

👉 点击关注我进阶深化下篇更新后第一时间推送!

相关推荐
TeamDev1 小时前
在 Excel 加载项中嵌入 Web 视图
前端·后端·.net
LinDaiDai_霖呆呆1 小时前
大白话介绍大模型的一些底层原理,看完终于能跟人聊两句了
前端·人工智能·面试
Mr_愚人派1 小时前
redis_点评详解(02.短信登录-验证码登录注册)
后端
Xidaoapi1 小时前
5分钟让你的Python项目接入GPT-4:从配置到上线的完整指南
后端
SamDeepThinking1 小时前
写代码不考虑前后兼容,迟早要还的
java·后端·程序员
亿牛云爬虫专家1 小时前
深度解析:数据采集场景下的 Java 代理技术实战
java·开发语言·数据采集·动态ip·动态代理·代理配置·连接池复用
小小仙。2 小时前
IT自学第四十二天
java·开发语言
java1234_小锋2 小时前
说一下Spring的事务传播行为?
java·数据库·spring
庞轩px2 小时前
第四篇:SpringBoot自动配置——约定大于配置的底层原理
java·spring boot·后端·spring·自动配置·注解开发