[{"data":1,"prerenderedAt":636},["ShallowReactive",2],{"java:spring\u002F":3,"java-wiki-navigation":113},{"id":4,"title":5,"body":6,"commentId":99,"description":100,"difficulty":101,"draft":102,"extension":103,"meta":104,"navigation":105,"order":106,"path":107,"section":108,"seo":109,"stem":110,"updated":111,"__hash__":112},"java\u002Fjava\u002Fspring.md","Spring 知识地图",{"type":7,"value":8,"toc":90},"minimark",[9,14,18,22,41,45,59,62,79,82],[10,11,13],"h2",{"id":12},"理解-spring-的主线","理解 Spring 的主线",[15,16,17],"p",{},"Spring 的核心不是注解数量，而是容器如何创建对象、建立依赖，并在合适的扩展点改变对象行为。",[10,19,21],{"id":20},"ioc-容器","IOC 容器",[23,24,25,29,32,35,38],"ul",{},[26,27,28],"li",{},"BeanDefinition 的来源",[26,30,31],{},"Bean 创建生命周期",[26,33,34],{},"依赖注入",[26,36,37],{},"BeanPostProcessor",[26,39,40],{},"循环依赖",[10,42,44],{"id":43},"aop","AOP",[23,46,47,50,53,56],{},[26,48,49],{},"JDK 动态代理和 CGLIB",[26,51,52],{},"切点与通知",[26,54,55],{},"代理对象调用边界",[26,57,58],{},"自调用为什么可能导致切面失效",[10,60,61],{"id":61},"事务",[23,63,64,67,70,73,76],{},[26,65,66],{},"事务管理器",[26,68,69],{},"传播行为",[26,71,72],{},"隔离级别",[26,74,75],{},"回滚规则",[26,77,78],{},"声明式事务失效场景",[10,80,81],{"id":81},"学习建议",[15,83,84,85,89],{},"选择一条最短链路，从 ",[86,87,88],"code",{},"ApplicationContext"," 启动到一个带事务的 Service 被调用，跟踪其中的对象创建、代理生成和拦截过程。这样比孤立背诵源码类名更有效。",{"title":91,"searchDepth":92,"depth":92,"links":93},"",2,[94,95,96,97,98],{"id":12,"depth":92,"text":13},{"id":20,"depth":92,"text":21},{"id":43,"depth":92,"text":44},{"id":61,"depth":92,"text":61},{"id":81,"depth":92,"text":81},"wiki:java:spring","从 IOC、AOP 和事务出发，理解 Spring 如何组织和增强应用程序。","intermediate",false,"md",{},true,4,"\u002Fjava\u002Fspring","Spring",{"title":5,"description":100},"java\u002Fspring","2026-07-10","jZmHr0WwrtcGUGlcEdj8z-shlR3YZc-UdEZSfPZYgNE",[114,203,315,422,484,560],{"id":115,"title":116,"body":117,"commentId":193,"description":194,"difficulty":195,"draft":102,"extension":103,"meta":196,"navigation":105,"order":197,"path":198,"section":199,"seo":200,"stem":201,"updated":111,"__hash__":202},"java\u002Fjava\u002Ffundamentals.md","Java 基础知识地图",{"type":7,"value":118,"toc":187},[119,122,125,128,152,155,158,161],[10,120,121],{"id":121},"这一部分解决什么问题",[15,123,124],{},"Java 基础不是 API 的罗列，而是理解类型、对象和运行时行为之间的关系。后续的并发、JVM 和框架知识都建立在这些概念之上。",[10,126,127],{"id":127},"知识路线",[129,130,131,134,140,143,146,149],"ol",{},[26,132,133],{},"基本类型、包装类型与自动装箱",[26,135,136,139],{},[86,137,138],{},"String","、不可变对象与对象比较",[26,141,142],{},"集合框架与常见数据结构",[26,144,145],{},"泛型、类型擦除与边界",[26,147,148],{},"反射、注解与动态代理",[26,150,151],{},"异常体系和资源管理",[10,153,154],{"id":154},"推荐学习方式",[15,156,157],{},"先用一句话回答“它是什么”，再通过小段代码验证边界，最后把它放回 JVM 和框架运行机制中理解。知识库会逐步把每个主题拆成独立条目。",[10,159,160],{"id":160},"面试时容易出现的问题",[23,162,163,170,181,184],{},[26,164,165,166,169],{},"只背诵 ",[86,167,168],{},"HashMap"," 的结论，不理解哈希冲突和扩容成本。",[26,171,172,173,176,177,180],{},"把 ",[86,174,175],{},"=="," 和 ",[86,178,179],{},"equals"," 简化成“地址比较”和“内容比较”。",[26,182,183],{},"知道泛型语法，但无法解释类型擦除带来的限制。",[26,185,186],{},"会使用反射，却不了解它为什么被 Spring 等框架广泛使用。",{"title":91,"searchDepth":92,"depth":92,"links":188},[189,190,191,192],{"id":121,"depth":92,"text":121},{"id":127,"depth":92,"text":127},{"id":154,"depth":92,"text":154},{"id":160,"depth":92,"text":160},"wiki:java:fundamentals","Java 类型系统、集合、泛型、反射、异常与常用语言机制的学习入口。","basic",{},1,"\u002Fjava\u002Ffundamentals","Java 基础",{"title":116,"description":194},"java\u002Ffundamentals","TZ18cq4bXSr9iscSOTSlgfMfbmTp2H5kOdVxAbnY_2s",{"id":204,"title":205,"body":206,"commentId":307,"description":308,"difficulty":101,"draft":102,"extension":103,"meta":309,"navigation":105,"order":92,"path":310,"section":311,"seo":312,"stem":313,"updated":111,"__hash__":314},"java\u002Fjava\u002Fjvm.md","JVM 知识地图",{"type":7,"value":207,"toc":296},[208,212,215,217,221,235,238,252,255,269,272,286,289],[10,209,211],{"id":210},"为什么要理解-jvm","为什么要理解 JVM",[15,213,214],{},"JVM 把 Java 源代码和具体硬件隔开，但生产问题最终仍会落到内存、线程、字节码和操作系统资源上。理解 JVM 的目标不是记参数，而是能解释和诊断程序行为。",[10,216,127],{"id":127},[218,219,220],"h3",{"id":220},"类加载",[23,222,223,226,229,232],{},[26,224,225],{},"加载、验证、准备、解析和初始化",[26,227,228],{},"双亲委派模型",[26,230,231],{},"类加载器隔离",[26,233,234],{},"静态字段和初始化顺序",[218,236,237],{"id":237},"运行时数据区",[23,239,240,243,246,249],{},[26,241,242],{},"堆与对象分配",[26,244,245],{},"虚拟机栈与栈帧",[26,247,248],{},"方法区与元空间",[26,250,251],{},"直接内存",[218,253,254],{"id":254},"垃圾回收",[23,256,257,260,263,266],{},[26,258,259],{},"可达性分析",[26,261,262],{},"分代收集",[26,264,265],{},"CMS、G1 与现代收集器",[26,267,268],{},"停顿时间、吞吐量和内存占用之间的权衡",[218,270,271],{"id":271},"性能排查",[23,273,274,277,280,283],{},[26,275,276],{},"GC 日志",[26,278,279],{},"线程快照",[26,281,282],{},"堆转储",[26,284,285],{},"CPU、内存和锁竞争定位",[10,287,288],{"id":288},"一句话原则",[15,290,291,292,295],{},"先确定现象属于 CPU、内存、线程还是外部依赖，再选择工具；不要看到 ",[86,293,294],{},"OutOfMemoryError"," 就先调整堆大小。",{"title":91,"searchDepth":92,"depth":92,"links":297},[298,299,306],{"id":210,"depth":92,"text":211},{"id":127,"depth":92,"text":127,"children":300},[301,303,304,305],{"id":220,"depth":302,"text":220},3,{"id":237,"depth":302,"text":237},{"id":254,"depth":302,"text":254},{"id":271,"depth":302,"text":271},{"id":288,"depth":92,"text":288},"wiki:java:jvm","从类加载、运行时内存到垃圾回收与性能排查，理解 Java 程序如何真正运行。",{},"\u002Fjava\u002Fjvm","JVM",{"title":205,"description":308},"java\u002Fjvm","ZPK0OT5czgBvYvU-AowqKfXfaGqS5bqnDP2N5bWKN5k",{"id":316,"title":317,"body":318,"commentId":414,"description":415,"difficulty":101,"draft":102,"extension":103,"meta":416,"navigation":105,"order":302,"path":417,"section":418,"seo":419,"stem":420,"updated":111,"__hash__":421},"java\u002Fjava\u002Fconcurrency.md","Java 并发知识地图",{"type":7,"value":319,"toc":405},[320,323,326,333,336,346,349,352,354,388,391],[10,321,322],{"id":322},"并发问题的三个核心维度",[218,324,325],{"id":325},"可见性",[15,327,328,329,332],{},"一个线程修改的数据，何时能够被另一个线程观察到。",[86,330,331],{},"volatile","、锁和线程启动\u002F终止规则都与 happens-before 有关。",[218,334,335],{"id":335},"原子性",[15,337,338,339,342,343,345],{},"一个操作能否被其他线程观察到中间状态。",[86,340,341],{},"count++"," 即使使用 ",[86,344,331],{}," 也不是原子操作。",[218,347,348],{"id":348},"有序性",[15,350,351],{},"编译器和处理器可以在不改变单线程结果的前提下重排序。并发程序必须通过同步规则建立必要顺序。",[10,353,127],{"id":127},[129,355,356,359,364,370,373,376,379,385],{},[26,357,358],{},"Java 内存模型与 happens-before",[26,360,361,363],{},[86,362,331],{}," 与内存屏障",[26,365,366,369],{},[86,367,368],{},"synchronized"," 与对象监视器",[26,371,372],{},"CAS、原子类和 ABA 问题",[26,374,375],{},"AQS、锁和同步器",[26,377,378],{},"线程池与任务调度",[26,380,381,384],{},[86,382,383],{},"CompletableFuture"," 与异步编排",[26,386,387],{},"并发容器",[10,389,390],{"id":390},"生产实践原则",[23,392,393,396,399,402],{},[26,394,395],{},"尽量减少共享可变状态。",[26,397,398],{},"明确线程池的职责、队列容量和拒绝策略。",[26,400,401],{},"不要把耗时不可控的任务提交到公共线程池。",[26,403,404],{},"监控活跃线程数、队列长度、拒绝次数和任务耗时。",{"title":91,"searchDepth":92,"depth":92,"links":406},[407,412,413],{"id":322,"depth":92,"text":322,"children":408},[409,410,411],{"id":325,"depth":302,"text":325},{"id":335,"depth":302,"text":335},{"id":348,"depth":302,"text":348},{"id":127,"depth":92,"text":127},{"id":390,"depth":92,"text":390},"wiki:java:concurrency","理解可见性、原子性、有序性，以及 Java 并发工具如何建立在这些规则之上。",{},"\u002Fjava\u002Fconcurrency","并发编程",{"title":317,"description":415},"java\u002Fconcurrency","EkMZP12_4LdF-05WBbKP344weaqz3uif-3l5nazF3xk",{"id":4,"title":5,"body":423,"commentId":99,"description":100,"difficulty":101,"draft":102,"extension":103,"meta":482,"navigation":105,"order":106,"path":107,"section":108,"seo":483,"stem":110,"updated":111,"__hash__":112},{"type":7,"value":424,"toc":475},[425,427,429,431,443,445,455,457,469,471],[10,426,13],{"id":12},[15,428,17],{},[10,430,21],{"id":20},[23,432,433,435,437,439,441],{},[26,434,28],{},[26,436,31],{},[26,438,34],{},[26,440,37],{},[26,442,40],{},[10,444,44],{"id":43},[23,446,447,449,451,453],{},[26,448,49],{},[26,450,52],{},[26,452,55],{},[26,454,58],{},[10,456,61],{"id":61},[23,458,459,461,463,465,467],{},[26,460,66],{},[26,462,69],{},[26,464,72],{},[26,466,75],{},[26,468,78],{},[10,470,81],{"id":81},[15,472,84,473,89],{},[86,474,88],{},{"title":91,"searchDepth":92,"depth":92,"links":476},[477,478,479,480,481],{"id":12,"depth":92,"text":13},{"id":20,"depth":92,"text":21},{"id":43,"depth":92,"text":44},{"id":61,"depth":92,"text":61},{"id":81,"depth":92,"text":81},{},{"title":5,"description":100},{"id":485,"title":486,"body":487,"commentId":551,"description":552,"difficulty":101,"draft":102,"extension":103,"meta":553,"navigation":105,"order":554,"path":555,"section":556,"seo":557,"stem":558,"updated":111,"__hash__":559},"java\u002Fjava\u002Fdatabase.md","数据库与缓存知识地图",{"type":7,"value":488,"toc":545},[489,492,495,499,519,522,539,542],[10,490,491],{"id":491},"数据库知识的核心问题",[15,493,494],{},"后端开发关注的不只是 SQL 能否执行，还要理解数据如何被定位、并发修改如何协调、失败后如何恢复，以及缓存加入后怎样维持可接受的一致性。",[10,496,498],{"id":497},"mysql","MySQL",[23,500,501,504,507,510,513,516],{},[26,502,503],{},"B+Tree 与索引组织",[26,505,506],{},"联合索引和最左匹配",[26,508,509],{},"执行计划",[26,511,512],{},"MVCC 与 Read View",[26,514,515],{},"行锁、间隙锁和死锁",[26,517,518],{},"redo log、undo log 与 binlog",[10,520,521],{"id":521},"缓存",[23,523,524,527,530,533,536],{},[26,525,526],{},"Cache Aside",[26,528,529],{},"缓存穿透、击穿和雪崩",[26,531,532],{},"热点 Key",[26,534,535],{},"数据更新与失效",[26,537,538],{},"最终一致性",[10,540,541],{"id":541},"排查顺序",[15,543,544],{},"面对慢查询，先确认实际执行 SQL 和参数，再看执行计划、扫描行数、锁等待和数据分布。不要只根据 SQL 外观判断是否使用索引。",{"title":91,"searchDepth":92,"depth":92,"links":546},[547,548,549,550],{"id":491,"depth":92,"text":491},{"id":497,"depth":92,"text":498},{"id":521,"depth":92,"text":521},{"id":541,"depth":92,"text":541},"wiki:java:database","围绕索引、事务、锁、缓存与数据一致性，建立后端开发需要的数据库认知。",{},5,"\u002Fjava\u002Fdatabase","数据库",{"title":486,"description":552},"java\u002Fdatabase","3gza7dGQZPwMSHFISiZ7Jy-iB_2rQD2ozomZ8OuiyHw",{"id":561,"title":562,"body":563,"commentId":627,"description":628,"difficulty":195,"draft":102,"extension":103,"meta":629,"navigation":105,"order":630,"path":631,"section":632,"seo":633,"stem":634,"updated":111,"__hash__":635},"java\u002Fjava\u002Finterview.md","Java 面试专题使用说明",{"type":7,"value":564,"toc":622},[565,568,571,574,607,610,619],[10,566,567],{"id":567},"这里不会做什么",[15,569,570],{},"不会把数百道问题堆在一个页面，也不会只给出适合背诵但无法解释的标准答案。",[10,572,573],{"id":573},"每个问题的组织方式",[129,575,576,583,589,595,601],{},[26,577,578,582],{},[579,580,581],"strong",{},"一句话回答","：先准确回答问题。",[26,584,585,588],{},[579,586,587],{},"核心原理","：说明这个结论为什么成立。",[26,590,591,594],{},[579,592,593],{},"代码验证","：使用尽可能小的例子验证边界。",[26,596,597,600],{},[579,598,599],{},"常见误区","：指出容易混淆的地方。",[26,602,603,606],{},[579,604,605],{},"继续追问","：把当前问题连接到更深层知识。",[10,608,609],{"id":609},"示例追问链",[611,612,617],"pre",{"className":613,"code":615,"language":616,"meta":91},[614],"language-text","HashMap 为什么线程不安全？\n  → put 操作包含哪些步骤？\n  → 扩容时发生什么？\n  → ConcurrentHashMap 如何降低竞争？\n  → JDK 不同版本的实现有什么变化？\n","text",[86,618,615],{"__ignoreMap":91},[15,620,621],{},"面试题的价值不是预测题目，而是帮助自己检查知识之间是否已经形成连接。",{"title":91,"searchDepth":92,"depth":92,"links":623},[624,625,626],{"id":567,"depth":92,"text":567},{"id":573,"depth":92,"text":573},{"id":609,"depth":92,"text":609},"wiki:java:interview","用简明回答、原理解释、代码验证和追问路径组织 Java 面试知识。",{},6,"\u002Fjava\u002Finterview","面试专题",{"title":562,"description":628},"java\u002Finterview","AWxAYmdi1IahbXu7QwVZPfsiCXbVU4YTMMoshQkzEl8",1783807996405]