<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>八股 on Evorsio</title><link>https://blog.evorsio.com/tags/%E5%85%AB%E8%82%A1/</link><description>Recent content in 八股 on Evorsio</description><generator>Hugo -- gohugo.io</generator><language>zh</language><lastBuildDate>Tue, 21 Apr 2026 10:30:00 +1200</lastBuildDate><atom:link href="https://blog.evorsio.com/tags/%E5%85%AB%E8%82%A1/index.xml" rel="self" type="application/rss+xml"/><item><title>Java 八股</title><link>https://blog.evorsio.com/p/java-interview-notes/</link><pubDate>Sun, 19 Apr 2026 23:00:00 +1200</pubDate><guid>https://blog.evorsio.com/p/java-interview-notes/</guid><description>&lt;h1 id="java-后端开发八股"&gt;Java 后端开发八股
&lt;/h1&gt;&lt;h2 id="基础语法"&gt;基础语法
&lt;/h2&gt;&lt;h3 id="基本类型"&gt;基本类型
&lt;/h3&gt;&lt;p&gt;8 种基本类型，分为四类&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;类型类别&lt;/th&gt;
 &lt;th&gt;数据类型&lt;/th&gt;
 &lt;th&gt;占用字节&lt;/th&gt;
 &lt;th&gt;默认值&lt;/th&gt;
 &lt;th&gt;说明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;整数&lt;/td&gt;
 &lt;td&gt;byte&lt;/td&gt;
 &lt;td&gt;1&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;最小整数类型&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;整数&lt;/td&gt;
 &lt;td&gt;short&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;短整型&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;整数&lt;/td&gt;
 &lt;td&gt;int&lt;/td&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;0&lt;/td&gt;
 &lt;td&gt;常用整数类型&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;整数&lt;/td&gt;
 &lt;td&gt;long&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;0L&lt;/td&gt;
 &lt;td&gt;长整数类型&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;浮点&lt;/td&gt;
 &lt;td&gt;float&lt;/td&gt;
 &lt;td&gt;4&lt;/td&gt;
 &lt;td&gt;0.0f&lt;/td&gt;
 &lt;td&gt;单精度浮点&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;浮点&lt;/td&gt;
 &lt;td&gt;double&lt;/td&gt;
 &lt;td&gt;8&lt;/td&gt;
 &lt;td&gt;0.0d&lt;/td&gt;
 &lt;td&gt;双精度浮点（默认）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;字符&lt;/td&gt;
 &lt;td&gt;char&lt;/td&gt;
 &lt;td&gt;2&lt;/td&gt;
 &lt;td&gt;&amp;lsquo;\u0000&amp;rsquo;&lt;/td&gt;
 &lt;td&gt;Unicode 字符&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;布尔&lt;/td&gt;
 &lt;td&gt;boolean&lt;/td&gt;
 &lt;td&gt;1（JVM 依实现）&lt;/td&gt;
 &lt;td&gt;false&lt;/td&gt;
 &lt;td&gt;逻辑值 true/false&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="object-类有哪些方法"&gt;Object 类有哪些方法？
&lt;/h3&gt;&lt;p&gt;共 1 1 个，去掉重载一共有 9 种方法&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;方法&lt;/th&gt;
 &lt;th&gt;返回类型&lt;/th&gt;
 &lt;th&gt;作用&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;getClass()&lt;/td&gt;
 &lt;td&gt;Class&lt;?&gt;&lt;/td&gt;
 &lt;td&gt;获取运行时类信息&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;hashCode()&lt;/td&gt;
 &lt;td&gt;int&lt;/td&gt;
 &lt;td&gt;返回对象哈希值&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;equals(Object obj)&lt;/td&gt;
 &lt;td&gt;boolean&lt;/td&gt;
 &lt;td&gt;判断对象是否相等&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;toString()&lt;/td&gt;
 &lt;td&gt;String&lt;/td&gt;
 &lt;td&gt;返回对象字符串表示&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;clone()&lt;/td&gt;
 &lt;td&gt;Object&lt;/td&gt;
 &lt;td&gt;克隆对象（需实现 Cloneable）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;finalize()&lt;/td&gt;
 &lt;td&gt;void&lt;/td&gt;
 &lt;td&gt;GC 回收前调用（已过时）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;wait()&lt;/td&gt;
 &lt;td&gt;void&lt;/td&gt;
 &lt;td&gt;线程等待（需在同步块中）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;wait(long timeout)&lt;/td&gt;
 &lt;td&gt;void&lt;/td&gt;
 &lt;td&gt;带超时等待&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;wait(long timeout, int nanos)&lt;/td&gt;
 &lt;td&gt;void&lt;/td&gt;
 &lt;td&gt;更精细等待&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;notify()&lt;/td&gt;
 &lt;td&gt;void&lt;/td&gt;
 &lt;td&gt;唤醒一个等待线程&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;notifyAll()&lt;/td&gt;
 &lt;td&gt;void&lt;/td&gt;
 &lt;td&gt;唤醒所有等待线程&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="string-s--new-stringhello会创建几个对象"&gt;&lt;code&gt;String s = new String(&amp;quot;hello&amp;quot;);&lt;/code&gt;会创建几个对象?
&lt;/h3&gt;&lt;p&gt;1 个或 2 个对象&lt;/p&gt;
&lt;p&gt;分情况讨论:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;常量池没有 &amp;ldquo;hello&amp;rdquo;： 创建 2 个对象：常量池 &amp;ldquo;hello&amp;rdquo; 和 堆中 new String(&amp;ldquo;hello&amp;rdquo;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;常量池已有 &amp;ldquo;hello&amp;rdquo;： 创建 1 个对象：堆中 new String(&amp;ldquo;hello&amp;rdquo;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="创建对象实例的方式有几种"&gt;创建对象实例的方式有几种？
&lt;/h3&gt;&lt;p&gt;4 种&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;方式&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;th&gt;说明&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;1. new 关键字&lt;/td&gt;
 &lt;td&gt;User u = new User();&lt;/td&gt;
 &lt;td&gt;最常用，直接调用构造方法&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;2. 反射机制&lt;/td&gt;
 &lt;td&gt;User u = (User) Class.forName(&amp;ldquo;User&amp;rdquo;).newInstance();&lt;/td&gt;
 &lt;td&gt;运行时创建对象&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;3. Clone 克隆&lt;/td&gt;
 &lt;td&gt;User u2 = (User) u1.clone();&lt;/td&gt;
 &lt;td&gt;通过对象复制创建（浅拷贝）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;4. 反序列化&lt;/td&gt;
 &lt;td&gt;User u = (User) ObjectInputStream.readObject();&lt;/td&gt;
 &lt;td&gt;从文件/网络恢复对象&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="为什么-equals-和-hashcode-要同时重写"&gt;为什么 equals() 和 hashcode() 要同时重写？
&lt;/h3&gt;&lt;p&gt;JDK 规范中，如果两个对象 &lt;strong&gt;equals() 返回 true（逻辑相等）&lt;/strong&gt;，那么它们的 &lt;strong&gt;hashCode 必须相同&lt;/strong&gt;；反之不成立，因为可能发生哈希冲突。&lt;/p&gt;
&lt;p&gt;在 HashSet / HashMap 中，hashCode 决定“存放位置”，equals 决定“是否重复”，如果只重写一个，会导致逻辑不一致，出现重复数据或查找失败。&lt;/p&gt;
&lt;h3 id="-和-equals-的区别"&gt;== 和 equals() 的区别
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;==&lt;/code&gt; 比较的是引用地址（或基本类型值），&lt;code&gt;equals()&lt;/code&gt; 在 Object 类中默认比较地址，但在包装类中可以重写为比较内容，因此一般用于对象逻辑相等判断。&lt;/p&gt;
&lt;h3 id="抽象类和接口的区别"&gt;抽象类和接口的区别
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;对比项&lt;/th&gt;
 &lt;th&gt;抽象类（abstract class）&lt;/th&gt;
 &lt;th&gt;接口（interface）&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;是否可以实例化&lt;/td&gt;
 &lt;td&gt;❌ 不可以&lt;/td&gt;
 &lt;td&gt;❌ 不可以&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;方法&lt;/td&gt;
 &lt;td&gt;可以有抽象方法 + 具体方法&lt;/td&gt;
 &lt;td&gt;抽象方法 + default/static 方法（JDK8+）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;变量&lt;/td&gt;
 &lt;td&gt;可以有普通成员变量&lt;/td&gt;
 &lt;td&gt;只能是常量（public static final）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;构造方法&lt;/td&gt;
 &lt;td&gt;✔ 有&lt;/td&gt;
 &lt;td&gt;❌ 没有&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;继承方式&lt;/td&gt;
 &lt;td&gt;单继承&lt;/td&gt;
 &lt;td&gt;多实现&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;访问修饰符&lt;/td&gt;
 &lt;td&gt;可以任意&lt;/td&gt;
 &lt;td&gt;方法默认 public&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="为什么在-java-8-之后接口中可以有-defaultstatic-方法呢"&gt;为什么在 Java 8 之后接口中可以有 default/static 方法呢？
&lt;/h4&gt;&lt;p&gt;Java 8 之后接口引入 default 和 static 方法，是为了在不破坏已有实现类的情况下扩展接口能力，同时支持函数式编程和工具方法集中管理。default 方法属于给实现类用的或重写的“默认行为”，static 方法属于属于接口本身的工具方法。&lt;/p&gt;
&lt;h3 id="类是什么"&gt;类是什么？
&lt;/h3&gt;&lt;p&gt;类（Class）是面向对象编程（OOP）中用来描述对象的结构和行为的基本构造单元。&lt;/p&gt;
&lt;h3 id="接口是什么"&gt;接口是什么？
&lt;/h3&gt;&lt;p&gt;接口（Interface）是面向对象编程（OOP）中用于定义行为规范的一种抽象机制。&lt;/p&gt;
&lt;h3 id="抽象类是什么"&gt;抽象类是什么？
&lt;/h3&gt;&lt;p&gt;抽象类（Abstract Class）是面向对象编程（OOP）中用于描述“部分抽象对象”的一种类类型。&lt;/p&gt;
&lt;h3 id="谈谈你对面向对象的理解"&gt;谈谈你对面向对象的理解
&lt;/h3&gt;&lt;p&gt;与面向过程相比，面向对象是一种以“对象”为中心来组织软件设计的编程思想，将数据与行为封装在一起，通过封装、继承和多态来模拟现实世界，从而降低系统复杂度并提升可扩展性。&lt;/p&gt;
&lt;h4 id="oop-的核心是什么"&gt;OOP 的核心是什么？
&lt;/h4&gt;&lt;p&gt;一切皆“对象”&lt;/p&gt;
&lt;p&gt;现实世界 → 抽象 → 对象 → 程序模型 ==&amp;gt; 人、车、订单、商品 → 都可以抽象成对象&lt;/p&gt;
&lt;h4 id="oop-三大核心特性"&gt;OOP 三大核心特性
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;封装（Encapsulation）：把数据和行为封装在一起，对外隐藏内部实现&lt;/li&gt;
&lt;li&gt;继承（Inheritance）：子类复用父类的属性和方法，实现代码复用&lt;/li&gt;
&lt;li&gt;多态（Polymorphism）：同一行为，不同实现，子类可以重写父类方法&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="stringbuilder-和-stringbuffer-的区别"&gt;StringBuilder 和 StringBuffer 的区别
&lt;/h3&gt;&lt;p&gt;StringBuffer 线程安全（方法使用 synchronized 修饰），StringBuilder 非线程安全&lt;/p&gt;
&lt;h3 id="error-和-exception-的区别"&gt;Error 和 Exception 的区别
&lt;/h3&gt;&lt;p&gt;Error 是 JVM 层面的严重错误，通常表示系统级问题，程序一般无法处理；Exception 是程序运行过程中可能出现的异常情况，程序可以捕获并处理。&lt;/p&gt;
&lt;p&gt;Exception 又分为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;受检异常（Checked Exception）：编译期必须处理（try-catch 或 throws），否则无法通过编译&lt;/li&gt;
&lt;li&gt;运行时异常（RuntimeException）：编译期不强制处理，运行时抛出，通常由程序逻辑错误引起，但也可以捕获处理&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;graph TD
 A[Throwable] --&gt; B[Error]
 A --&gt; C[Exception]

 B --&gt; B1[OutOfMemoryError]
 B --&gt; B2[StackOverflowError]
 B --&gt; B3[NoClassDefFoundError]

 C --&gt; D[Checked Exception]
 C --&gt; E[RuntimeException]

 D --&gt; D1[IOException]
 D --&gt; D2[SQLException]
 D --&gt; D3[FileNotFoundException]

 E --&gt; E1[NullPointerException]
 E --&gt; E2[ArrayIndexOutOfBoundsException]
 E --&gt; E3[ClassCastException]
 E --&gt; E4[ArithmeticException]&lt;/pre&gt;&lt;h3 id="对象的组成"&gt;对象的组成
&lt;/h3&gt;&lt;p&gt;由三大部分组成， 对象头（Object Header），实例数据（Instance Data），对齐填充（Padding）&lt;/p&gt;
&lt;h5 id="对象头"&gt;对象头
&lt;/h5&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Mark Word （8 个字节）&lt;/p&gt;
&lt;p&gt;&lt;img alt="markword" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="C:\\Users\\Admin\\Downloads\\markword.png"&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Klass Pointer （ 8 个字节，如果开启了指针压缩（默认）是 4 个字节）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;数组长度（length，如果是数组对象）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h5 id="实例数据"&gt;实例数据
&lt;/h5&gt;&lt;p&gt;class User {
int id; // 4 字节
long age; // 8 字节
Object obj; // 4 字节（引用）
}&lt;/p&gt;
&lt;h5 id="对齐填充"&gt;对齐填充
&lt;/h5&gt;&lt;p&gt;保证对象总大小是 8 字节的整数倍， 因为 JVM 内存分配是按 8 字节对齐的&lt;/p&gt;
&lt;p&gt;在 64 位 JVM（开启指针压缩）下，User 对象包含&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;12 字节对象头（Mark Word + Klass Pointer）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;16 字节实例数据（long 8B + int 4B + obj 引用 4B，JVM 会重排对齐）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对齐填充 4 字节&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;最终大小为 &lt;strong&gt;32 字节&lt;/strong&gt;。&lt;/p&gt;
&lt;h5 id="反射的原理"&gt;反射的原理
&lt;/h5&gt;&lt;p&gt;在运行时通过 Class 元信息 + 方法表 + 常量池解析，动态调用方法或访问字段的一套机制。&lt;/p&gt;
&lt;h2 id="多线程"&gt;多线程
&lt;/h2&gt;&lt;h3 id="进程和线程的区别"&gt;进程和线程的区别
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;对比维度&lt;/th&gt;
 &lt;th&gt;进程&lt;/th&gt;
 &lt;th&gt;线程&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;定义&lt;/td&gt;
 &lt;td&gt;程序的一次执行实例，是资源分配的基本单位&lt;/td&gt;
 &lt;td&gt;进程中的执行单元，是 CPU 调度的基本单位&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;资源&lt;/td&gt;
 &lt;td&gt;拥有独立的内存空间和系统资源&lt;/td&gt;
 &lt;td&gt;共享所属进程的内存和资源&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;调度&lt;/td&gt;
 &lt;td&gt;由操作系统进行调度&lt;/td&gt;
 &lt;td&gt;由 CPU 进行调度&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;开销&lt;/td&gt;
 &lt;td&gt;创建和切换开销大&lt;/td&gt;
 &lt;td&gt;创建和切换开销小&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;独立性&lt;/td&gt;
 &lt;td&gt;进程之间相互独立&lt;/td&gt;
 &lt;td&gt;线程之间共享资源&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;稳定性&lt;/td&gt;
 &lt;td&gt;一个进程崩溃一般不影响其他进程&lt;/td&gt;
 &lt;td&gt;一个线程崩溃可能导致整个进程崩溃&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;通信方式&lt;/td&gt;
 &lt;td&gt;进程间通信（IPC），较复杂&lt;/td&gt;
 &lt;td&gt;线程间可直接共享内存，通信简单&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="线程的分类"&gt;线程的分类
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;用户线程（User Thread）由用户程序创建和管理，JVM 主要执行的线程&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;守护线程（Daemon Thread）为用户线程提供服务的后台线程，如 GC 线程&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="线程的创建方式"&gt;线程的创建方式
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;继承 Thread 类&lt;/strong&gt;，重写 &lt;code&gt;run()&lt;/code&gt; 方法&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实现 Runnable 接口&lt;/strong&gt;，重写 &lt;code&gt;run()&lt;/code&gt; 方法&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实现 Callable 接口 + FutureTask&lt;/strong&gt;，重写 &lt;code&gt;call()&lt;/code&gt; 方法（可返回结果）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通过线程池创建线程&lt;/strong&gt;（ExecutorService）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="线程的生命周期"&gt;线程的生命周期
&lt;/h3&gt;&lt;p&gt;通过&lt;code&gt;java.lang.Thread.State&lt;/code&gt;枚举定义的&lt;/p&gt;
&lt;p&gt;&lt;img alt="thread-life" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="C:\\Users\\Admin\\Downloads\\thread-life.png"&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新建 -&amp;gt; 可运行：调用 Thread 对象的 start()方法。&lt;/li&gt;
&lt;li&gt;可运行 -&amp;gt; 运行：被系统选中，获取 CPU 执行权。&lt;/li&gt;
&lt;li&gt;运行 -&amp;gt; 阻塞：请求获取无法马上获取的资源。&lt;/li&gt;
&lt;li&gt;运行 -&amp;gt; 等待：调用 Object 类的 wait()方法。&lt;/li&gt;
&lt;li&gt;运行 -&amp;gt; 超时等待：调用 Thread.sleep(long)或 Object.wait(long)方法，或者期待 join(long)的结束，或者锁定某个对象的 LockSupport.parkNanos()或 LockSupport.parkUntil()方法。&lt;/li&gt;
&lt;li&gt;运行 -&amp;gt; 终止：线程终止。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="start和run方法有什么区别"&gt;&lt;code&gt;start()&lt;/code&gt;和&lt;code&gt;run()&lt;/code&gt;方法有什么区别
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;start()&lt;/code&gt; 是启动一个新线程，JVM 会为该线程分配独立的执行栈并调用 run() 方法&lt;/li&gt;
&lt;li&gt;&lt;code&gt;run()&lt;/code&gt; 只是普通方法调用，不会创建线程，直接在当前线程中执行。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="多线程安全问题和产生原因"&gt;多线程安全问题和产生原因
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;存在多个线程同时操作共享资源&lt;/li&gt;
&lt;li&gt;对共享资源的操作不是原子的&lt;/li&gt;
&lt;li&gt;线程执行由于 CPU 调度具有不确定性&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;解决方案：加锁（synchronized / Lock）保证同一时刻只有一个线程访问临界区&lt;/p&gt;
&lt;h3 id="synchronized-的底层原理"&gt;Synchronized 的底层原理
&lt;/h3&gt;&lt;h4 id="称呼层面"&gt;称呼层面
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;隐式锁&lt;/strong&gt;：由 JVM 自动加锁与释放，无需手动控制&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;悲观锁&lt;/strong&gt;：默认认为会发生竞争，访问前先加锁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;非公平锁&lt;/strong&gt;：不保证先来先得，线程获取锁具有随机性&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可重入锁&lt;/strong&gt;：同一线程可以重复获取同一把锁&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="状态层面"&gt;状态层面
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;无锁&lt;/strong&gt;（001）: 对象初始状态，没有线程竞争&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;偏向锁&lt;/strong&gt;（101）：无竞争时偏向第一个线程，减少 CAS 开销 （在 JDK 16 被彻底移除）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;轻量级锁&lt;/strong&gt;（00）：有少量竞争，通过 CAS 自旋获取锁&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;重量级锁&lt;/strong&gt;（10）：竞争激烈时升级为 Monitor 阻塞队列&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="语法层面"&gt;语法层面
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;
&lt;h5 id="作用于代码块编译后"&gt;作用于代码块（编译后）
&lt;/h5&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;code&gt;monitorenter&lt;/code&gt;：进入同步块获取 Monitor&lt;/p&gt;
&lt;p&gt;&lt;code&gt;monitorexit&lt;/code&gt;：退出同步块释放 Monitor&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;
&lt;h5 id="作用于方法编译后"&gt;作用于方法（编译后）
&lt;/h5&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;方法的方法表中有 flags: ACC_SYNCHRONIZED&lt;/p&gt;
&lt;h4 id="jvm-层面"&gt;JVM 层面
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;synchronized 底层依赖 Mark Word 与 Monitor 实现&lt;/li&gt;
&lt;li&gt;对象头的 Mark Word 中存储锁状态标志&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​ 倒数 2 位：锁标志位（lock flag）&lt;/p&gt;
&lt;p&gt;​ 第 3 位：偏向锁标志位（biased_lock）&lt;/p&gt;
&lt;ol start="3"&gt;
&lt;li&gt;在多线程竞争下，锁会发生升级（锁膨胀）以优化性能&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​ 先尝试偏向锁 (MarkWord 标记线程 ID)&lt;/p&gt;
&lt;p&gt;​ 有竞争时升级为轻量级锁(CAS+自旋+线程栈中 Lock Record)&lt;/p&gt;
&lt;p&gt;​ 多线程竞争时升级为重量级锁(ObjectMonitor（操作系统互斥量），线程进入阻塞状态（BLOCKED）)&lt;/p&gt;
&lt;p&gt;&lt;img alt="image-20260418184939926" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="C:\\Users\\Admin\\Desktop\\blog\\object-monitor.png"&gt;&lt;/p&gt;
&lt;h3 id="threadlocalmap-的底层原理"&gt;ThreadLocalMap 的底层原理
&lt;/h3&gt;&lt;h4 id="对象的四种引用方式"&gt;对象的四种引用方式
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;强引用：永不回收&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;软引用：内存不够才回收&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;弱引用：发现即回收&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;虚引用：不影响对象生命周期，用于回收通知&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="threadlocalmap-结构"&gt;ThreadLocalMap 结构
&lt;/h4&gt;&lt;p&gt;Entry:
key → WeakReference&lt;ThreadLocal&gt;
value → 强引用&lt;/p&gt;
&lt;h4 id="threadlocal-的-key-为什么是弱引用"&gt;ThreadLocal 的 key 为什么是弱引用
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;如果 key 是强引用，Thread → ThreadLocalMap → Entry → ThreadLocal，即使 tl = null，ThreadLocal 仍然被 Map 强引用， &lt;strong&gt;永远无法回收 → 内存泄漏&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;用弱引用之后 WeakReference(ThreadLocal)，下一次 GC：key → null， ThreadLocal 对象可以被回收。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="threadlocal-的-value-为什么是强引用"&gt;ThreadLocal 的 value 为什么是强引用
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;ThreadLocal 的 value 使用强引用，是因为它存储的是线程实际使用的数据，必须在使用期间保持稳定，不能被 GC 随意回收。&lt;/li&gt;
&lt;li&gt;因此设计上采用 key 使用弱引用避免 ThreadLocal 泄漏，而 value 使用强引用保证数据的正确性，并通过惰性清理机制处理 key 为 null 时的内存泄漏问题。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;ThreadLocal 的设计本质是一种基于 GC 约束的工程权衡。它通过弱引用 key 来解决 ThreadLocal 被 ThreadLocalMap 强引用导致的无意识内存泄漏问题，使 ThreadLocal 对象在外部失去引用后可以正常被 GC 回收。但 value 仍然使用强引用，以保证线程在执行期间数据的稳定性，避免业务数据被 GC 意外回收。这种设计的副作用是 key 被回收后 value 仍然残留在线程中，因此 ThreadLocal 将清理责任部分转移给开发者，通过在合适时机显式调用 remove() 来避免 value 泄漏。&lt;/p&gt;
&lt;h3 id="java-集合框架"&gt;Java 集合框架
&lt;/h3&gt;&lt;p&gt;Java 集合主要分为三大类接口体系：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Collection（单列集合）：用于存储 &lt;strong&gt;单个元素的集合&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;List（有序、可重复）：ArrayList，LinkedList&lt;/li&gt;
&lt;li&gt;Set（无序、不可重复）：HashSet，LinkedHashSet&lt;/li&gt;
&lt;li&gt;Queue（先进先出）：&lt;strong&gt;PriorityQueue&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Map（双列集合）：用于存储&lt;strong&gt;键值对（key-value）结构&lt;/strong&gt;。
&lt;ul&gt;
&lt;li&gt;HashMap&lt;/li&gt;
&lt;li&gt;LinkedHashMap&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="arraylist-扩容机制和底层原理"&gt;ArrayList 扩容机制和底层原理
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;ArrayList 底层基于 Object[] 动态数组实现，默认是空数组。&lt;/li&gt;
&lt;li&gt;第一次添加元素时才初始化容量，一般会变为 10。&lt;/li&gt;
&lt;li&gt;当数组容量不足时（即 size 超过当前数组长度），会触发扩容机制，扩容规则是原容量的 1.5 倍。扩容过程包括创建一个更大的新数组，将旧数组中的元素通过数组拷贝方式（System.arraycopy）复制到新数组中，最后用新数组替换旧数组引用。&lt;/li&gt;
&lt;li&gt;由于底层是数组结构，所以 ArrayList 查询效率较高，但插入和删除需要移动元素，性能较低，同时扩容时会有额外的拷贝开销。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="arraylist-和-linkedlist-的区别"&gt;ArrayList 和 LinkedList 的区别
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;ArrayList 底层是基于动态数组实现的，支持通过下标快速访问元素，因此查询效率为 O(1)，但在插入和删除时需要移动元素，效率较低。&lt;/li&gt;
&lt;li&gt;LinkedList 底层是双向链表结构，查询需要从头遍历，因此效率为 O(n)，但在插入和删除时只需要修改节点指针，因此效率较高。&lt;/li&gt;
&lt;li&gt;同时 ArrayList 内存占用较小，而 LinkedList 因为每个节点需要保存前后指针，内存开销更大。总体来说 ArrayList 适合查询多的场景，LinkedList 适合插入删除多的场景。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="arraylist-线程不安全体现和解决方案"&gt;ArrayList 线程不安全体现和解决方案
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;ArrayList 线程不安全的原因在于其 add 操作中的 size++ 不是原子操作，多线程同时修改会导致数据丢失或覆盖，同时扩容过程中也可能发生并发冲突。&lt;/li&gt;
&lt;li&gt;此外，在遍历过程中如果发生结构修改，还会触发 fail-fast 机制，抛出 ConcurrentModificationException。解决方案包括使用 Vector（方法级加锁，性能较差）、Collections.synchronizedList（对 ArrayList 进行同步包装，但迭代需手动加锁），以及 CopyOnWriteArrayList（写时复制，读不加锁，适合读多写少场景，是推荐方案）。&lt;/li&gt;
&lt;li&gt;ArrayList 有自己的内部迭代器实现（ListIterator），属于 fail-fast 机制。在使用普通迭代器（Iterator）遍历集合时，如果对集合结构进行修改（如 add 或 remove），会导致 modCount 和 expectedModCount 不一致，从而触发 ConcurrentModificationException。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="copyonwritearraylist-底层实现和原理"&gt;CopyOnWriteArrayList 底层实现和原理
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;CopyOnWriteArrayList 底层只有一个核心字段：&lt;code&gt;volatile Object[] array&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;核心思想: 写时复制（Copy On Write）,读：直接用旧数组（不加锁）, 写：复制新数组，在新数组上修改，再替换引用。&lt;/li&gt;
&lt;li&gt;写操作加锁，在 JDK 6 以前用的 ReentrantLock，JDK 7 及以后改为 synchronized，写操作很简单，不需要 ReentrantLock 的复杂能力，synchronized 已经优化得很好了，性能已经不差 ReentrantLock。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="hashmap-底层原理和实现"&gt;HashMap 底层原理和实现
&lt;/h3&gt;&lt;p&gt;HashMap 的底层结构是 &lt;strong&gt;数组 + 链表 + 红黑树&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="扩容机制"&gt;扩容机制
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;HashMap 的扩容本质就是 &lt;strong&gt;数组扩容 + 重新分布（rehash）&lt;/strong&gt;。&lt;/li&gt;
&lt;li&gt;默认初始容量是 16，负载因子是 0.75，当元素数量超过 &lt;code&gt;容量 × 负载因子&lt;/code&gt; 时就会触发扩容。扩容后容量变为原来的 2 倍，然后把原来所有元素重新计算位置（Java 8 之后做了优化，不是完全重新 hash，而是根据原 index + oldCap 判断去留，减少计算成本）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="两个参数"&gt;两个参数
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;初始容量（capacity）&lt;/strong&gt;：默认 16，决定桶数组大小&lt;/p&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;备注&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;HashMap 的初始容量默认是 16，但如果初始化时传入的不是 2 的幂，底层会通过 &lt;code&gt;tableSizeFor()&lt;/code&gt; 方法调整为大于等于该值的最小 2 的幂。这样做的目的是为了让 &lt;code&gt;(n - 1) &amp;amp; hash&lt;/code&gt; 的位运算更高效且分布更均匀。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;负载因子（load factor）&lt;/strong&gt;：默认 0.75，决定扩容阈值&lt;/p&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;备注&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;0.75 是在空间利用率和查询/插入性能之间的经验折中值。负载因子越大，HashMap 扩容越晚，桶内冲突概率越高（链表或红黑树变长），从而可能降低 &lt;code&gt;get()&lt;/code&gt; 和 &lt;code&gt;put()&lt;/code&gt; 的性能；但同时可以减少扩容次数，降低 rehash 的开销。&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;p&gt;扩容阈值 = capacity × loadFactor&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="两个算法"&gt;两个算法
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;计算元素脚标的算法：数组长度 -1 与 hashcode 值做与运算 &lt;code&gt;(index) = (n - 1) &amp;amp; hash&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;计算 hash 值的算法：&lt;strong&gt;Key 的 hashcode 值无符号右移十六位做异或运算&lt;/strong&gt; &lt;code&gt;hash = h ^ (h &amp;gt;&amp;gt;&amp;gt; 16)&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="成员方法"&gt;成员方法
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;put()&lt;/code&gt;：插入 key-value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get()&lt;/code&gt;：根据 key 查 value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remove()&lt;/code&gt;：删除元素&lt;/li&gt;
&lt;li&gt;&lt;code&gt;resize()&lt;/code&gt;：扩容方法&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hash()&lt;/code&gt;：计算 key 的 hash 值（扰动函数，减少冲突）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="hashmap-和-hashtable-的区别"&gt;HashMap 和 HashTable 的区别
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;HashMap 是线程不安全的，多线程环境下同时 put 可能导致数据覆盖、死循环（早期扩容链表反转问题）。
Hashtable 是线程安全的，它的方法基本都加了 &lt;code&gt;synchronized&lt;/code&gt; 锁，但代价是性能较低。现在一般不推荐使用 Hashtable，多线程场景通常用 &lt;code&gt;ConcurrentHashMap&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;HashMap 允许一个 null key 和多个 null value，因为它对 null key 做了特殊处理，不走 hash 计算，而是固定放在 0 号桶。
Hashtable 不允许任何 null key 或 null value，因为它在调用 hash 方法时直接做了 null 检查，避免空指针异常。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="hashmap-中-put-方法的执行流程"&gt;HashMap 中 put 方法的执行流程
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;对 key 进行 hash 计算&lt;/li&gt;
&lt;li&gt;根据 hash 定位数组下标&lt;/li&gt;
&lt;li&gt;如果该位置为空 → 直接插入&lt;/li&gt;
&lt;li&gt;如果不为空 → 发生冲突：
&lt;ul&gt;
&lt;li&gt;key 相同 → 直接覆盖 value&lt;/li&gt;
&lt;li&gt;key 不同 → 挂到链表后面&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;链表长度 ≥ 8 且数组长度 ≥ 64 → 转红黑树&lt;/li&gt;
&lt;li&gt;插入完成后判断是否需要扩容&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="hashmap-线程不安全的体现和解决方案"&gt;HashMap 线程不安全的体现和解决方案
&lt;/h3&gt;&lt;p&gt;体现&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;并发 put 导致数据覆盖&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;两个线程同时操作同一个桶&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;strong&gt;扩容时结构可能异常（JDK7 更严重）&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;多线程 resize 可能导致链表形成环（死循环）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;strong&gt;size 统计不准确&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;多线程同时修改 size 导致计数错误&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;解决方案&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;使用 ConcurrentHashMap&lt;/strong&gt;（推荐）&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;JDK8：CAS + synchronized（锁粒度更细）&lt;/li&gt;
&lt;li&gt;高并发性能好&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;使用 Collections.synchronizedMap()&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;给整个 Map 加一把大锁&lt;/li&gt;
&lt;li&gt;简单但性能差&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="concurrenthashmap-底层实现和原理"&gt;ConcurrentHashMap 底层实现和原理
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;put()&lt;/code&gt; 桶空 CAS + 桶非空 Synchronized&lt;/li&gt;
&lt;li&gt;JDK 7 分段锁（segment），JDK 8 锁链表头节点 + 红黑树树根节点&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="concurrenthashmap-是如何保证线程安全的"&gt;ConcurrentHashMap 是如何保证线程安全的？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;JDK 7：底层通过 Segment，继承自 ReentrantLock，初始化时有 16 个 Segment，每个 Segment 内部维护 HashEntry 数组（初始容量一般为 2），整体并不是只能存 32 个元素，而是每个 Segment 都可以扩容并存储大量元素，16 个 Segment 只是默认并发度配置。并发控制通过对 Segment 加锁实现，但锁的粒度较大（Segment 级别），在高并发下容易产生竞争，从而影响性能。&lt;/li&gt;
&lt;li&gt;JDK 8：底层采用数组+链表+红黑树结构，通过 CAS + Synchronized 保证线程安全。空桶情况下使用 CAS 进行无锁插入，发生哈希冲突时对桶进行加锁，锁的对象是链表的头节点或红黑树对应的 TreeBin 节点，锁粒度从 Segment 级别细化为桶级别，从而提升并发性能。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="concurrenthashmap-是为何不允许键值为-null"&gt;ConcurrentHashMap 是为何不允许键值为 null？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;无法区分“key 不存在”和“value 为 null”：&lt;/p&gt;
&lt;p&gt;在 ConcurrentHashMap 中，&lt;code&gt;get(key)&lt;/code&gt; 返回 null 在语义上是模糊的，它既可能表示 key 不存在，也可能表示 key 存在但 value 为 null。在单线程结构里可以通过额外判断来区分，但在并发环境下，这种状态可能在不同线程之间瞬间变化，导致判断结果不可靠，从而引发语义混乱。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;并发操作下 null 无法保证一致性&lt;/p&gt;
&lt;p&gt;ConcurrentHashMap 的 put、remove、resize 都是并发执行的，如果允许 value 为 null，那么一个线程写入 null 的过程中，另一个线程可能同时读取或修改该桶状态，导致无法判断当前看到的 null 是“真实值”、“未完成写入”还是“被删除后的状态”，从而破坏并发读写的一致性语义。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;简化底层实现（CAS + volatile + 红黑树结构）&lt;/p&gt;
&lt;p&gt;ConcurrentHashMap 的核心机制依赖 CAS、volatile 和桶级锁来实现高并发，如果允许 null，会导致 CAS 无法区分“空桶”和“值为 null”的状态，volatile 读到 null 时也无法判断语义，红黑树与链表结构中还需要额外处理 null 节点情况，因此设计上直接禁止 null，从而简化并发控制逻辑并避免边界复杂性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="jvm"&gt;JVM
&lt;/h2&gt;&lt;p&gt;User.java →（编译）→ User.class → &lt;strong&gt;类加载子系统&lt;/strong&gt;(加载,验证,准备,解析,初始化) → &lt;strong&gt;运行时数据区子系统(程序计数器，方法区，Java 堆，虚拟机栈，本地方法栈) ← 执行引擎子系统&lt;/strong&gt;（方法启动执行和垃圾回收）&lt;/p&gt;
&lt;h3 id="类加载器子系统"&gt;类加载器子系统
&lt;/h3&gt;&lt;p&gt;负责把 &lt;code&gt;.class&lt;/code&gt; 文件加载进 JVM。&lt;/p&gt;
&lt;p&gt;流程包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;加载（Loading）：读取 class 文件，生成 Class 对象&lt;/li&gt;
&lt;li&gt;验证（Verification）：检查字节码是否合法、安全&lt;/li&gt;
&lt;li&gt;准备（Preparation）：为 static 变量分配内存并赋默认值&lt;/li&gt;
&lt;li&gt;解析（Resolution）：符号引用转为直接引用&lt;/li&gt;
&lt;li&gt;初始化（Initialization）：执行 &lt;code&gt;&amp;lt;clinit&amp;gt;&lt;/code&gt;，初始化 static 变量&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="双亲委派"&gt;双亲委派
&lt;/h4&gt;&lt;h5 id="流程"&gt;流程
&lt;/h5&gt;&lt;p&gt;当一个类加载器收到类加载请求时，不会自己先加载，而是先委托给父加载器处理，逐层向上递归，直到启动类加载器（Bootstrap ClassLoader）。如果父加载器无法完成加载，子加载器才会尝试自己加载该类。&lt;/p&gt;
&lt;h5 id="好处"&gt;好处
&lt;/h5&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;避免类的重复加载&lt;/strong&gt;
同一个类不会被不同类加载器重复加载，保证 JVM 中 Class 的唯一性（同一个类在不同加载器下会被认为是不同类）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;保证核心类安全性&lt;/strong&gt;
防止用户自定义类覆盖 Java 核心类，例如 &lt;code&gt;java.lang.String&lt;/code&gt;，因为核心类优先由 Bootstrap ClassLoader 加载。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;保证类加载的层次结构稳定&lt;/strong&gt;
加载顺序具有严格的父子关系，结构清晰，避免混乱的类依赖加载问题。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="为什么-tomcat-和-jdbc-打破了双亲委派"&gt;为什么 tomcat 和 jdbc 打破了双亲委派？
&lt;/h3&gt;&lt;p&gt;tomcat:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Tomcat 是 Web 容器，一个核心需求是：不同 Web 应用之间必须隔离，且允许同名类版本不同，如果遵循双亲委派会导致所有类都会先交给父加载器（AppClassLoader / ExtClassLoader），&lt;strong&gt;所有应用共享同一份类 -&amp;gt; 无法隔离版本&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tomcat 的解决方案：自定义类加载器 + “反向委派”, Tomcat 设计了 WebAppClassLoader：加载顺序变成&lt;strong&gt;先自己找 → 找不到再委派父类&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;目的: 实现 Web 应用隔离（不同 war 包互不影响）,支持同名类不同版本共存, 避免全局污染（尤其是 lib 冲突）。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;jdbc:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;JDBC 的核心问题是：接口在 JDK 中，但实现类在第三方驱动中。如果严格双亲委派：DriverManager 在 Bootstrap ClassLoader，MySQL Driver 在 AppClassLoader，Bootstrap 不认识 AppClassLoader 加载的类。&lt;/li&gt;
&lt;li&gt;解决方式：SPI（服务发现机制），JDBC 使用：&lt;code&gt;ServiceLoader + Thread Context ClassLoader&lt;/code&gt;, DriverManager 在启动时不会自己加载具体 Driver, 而是通过：&lt;code&gt;Thread.currentThread().getContextClassLoader()&lt;/code&gt;去加载第三方驱动。&lt;/li&gt;
&lt;li&gt;本质：JDBC 并不是直接破坏双亲委派，而是&lt;strong&gt;绕过默认委派路径，改用线程上下文类加载器主动加载 SPI 实现类&lt;/strong&gt;，从而实现“接口在上层，实现在下层”的解耦结构。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="运行时数据区runtime-data-area"&gt;运行时数据区（Runtime Data Area）
&lt;/h3&gt;&lt;p&gt;JVM 的内存结构，用来存放运行时数据：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;堆（Heap）&lt;/strong&gt;：存对象实例（new 出来的东西）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;方法区（Method Area / MetaSpace）&lt;/strong&gt;：类信息、常量池、static 变量&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;虚拟机栈（Stack）&lt;/strong&gt;：方法调用栈帧（局部变量、方法调用）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;程序计数器（PC Register）&lt;/strong&gt;：记录当前线程执行到哪一行&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;本地方法栈（Native Stack）&lt;/strong&gt;：JNI 调用&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="执行引擎子系统execution-engine"&gt;执行引擎子系统（Execution Engine）
&lt;/h3&gt;&lt;p&gt;负责真正“执行代码”。&lt;/p&gt;
&lt;p&gt;包含：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;解释器（Interpreter）：逐行解释执行 bytecode&lt;/li&gt;
&lt;li&gt;JIT 编译器（Just-In-Time Compiler）：热点代码编译成本地机器码&lt;/li&gt;
&lt;li&gt;GC（垃圾回收器）：回收堆内存对象&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="如何判断一个对象为垃圾对象"&gt;如何判断一个对象为垃圾对象？
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;没有任何“GC Roots”可达的对象，就是垃圾对象。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GC Roots 常见来源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;虚拟机栈中的局部变量引用（方法里的对象）&lt;/li&gt;
&lt;li&gt;方法区中的静态变量（static）&lt;/li&gt;
&lt;li&gt;方法区中的常量&lt;/li&gt;
&lt;li&gt;JNI（Native 方法）引用&lt;/li&gt;
&lt;li&gt;正在运行的线程对象&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="内存泄漏和内存溢出有什么区别"&gt;内存泄漏和内存溢出有什么区别？
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;内存泄漏：对象&lt;strong&gt;不再使用&lt;/strong&gt;，但&lt;strong&gt;仍然被引用&lt;/strong&gt;，GC 回收不了，导致内存占用越来越高，最终可能导致 OOM。
&lt;ul&gt;
&lt;li&gt;static 集合一直存对象&lt;/li&gt;
&lt;li&gt;ThreadLocal 没 remove&lt;/li&gt;
&lt;li&gt;缓存无限增长&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;内存溢出（OutOfMemoryError）：JVM 申请不到更多内存了
&lt;ul&gt;
&lt;li&gt;内存泄漏积累&lt;/li&gt;
&lt;li&gt;加载超大对象&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="垃圾回收算法有哪些"&gt;垃圾回收算法有哪些？
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;标记清除：标记所有可达对象，清除未标记对象。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优点：简单&lt;/li&gt;
&lt;li&gt;缺点：1. 内存碎片严重 2.清理效率不稳定&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;标记复制（新生代常用 s0 s1）：内存分两块，一边用，一边空，存活对象复制到另一块。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优点：没有碎片，分配快&lt;/li&gt;
&lt;li&gt;缺点：内存浪费一半&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;标记整理（老年代常用）：标记存活对象, 向一端移动，清理边界外内存。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;优点：没有碎片，利用率高。&lt;/li&gt;
&lt;li&gt;缺点：移动对象成本高&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;分代收集&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="垃圾回收器有哪些"&gt;垃圾回收器有哪些？
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;串行垃圾回收器：
&lt;ul&gt;
&lt;li&gt;Serial 新生代 + Serial Old 老年代&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;并行垃圾回收器:
&lt;ul&gt;
&lt;li&gt;Parallel Scavenge 新生代 + Parallel Old 老年代 （JDK 8 默认）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;并发垃圾回收器:
&lt;ul&gt;
&lt;li&gt;ParNew 新生代 + CMS 老年代&lt;/li&gt;
&lt;li&gt;G1 （JDK 9 之后默认）&lt;/li&gt;
&lt;li&gt;ZGC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;G1 特点和实现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;堆被划分为多个 Region&lt;/li&gt;
&lt;li&gt;不再严格分代&lt;/li&gt;
&lt;li&gt;优先回收&lt;strong&gt;垃圾最多的区域&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;可预测停顿时间（比如 -XX:MaxGCPauseMillis）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;卡表和记忆集，三色标记法，SATB（Snapshot At The Beginning 解决漏标问题）&lt;/p&gt;
&lt;p&gt;ZGC 特点和实现：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GC 停顿时间：&lt;strong&gt;通常 &amp;lt; 10ms&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;大部分工作都放到&lt;strong&gt;与用户线程并发执行&lt;/strong&gt;， 只有极少阶段需要 STW&lt;/li&gt;
&lt;li&gt;支持 &lt;strong&gt;TB 级堆内存&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;内存多重映射，染色指针技术，读屏障&lt;/p&gt;
&lt;h3 id="jvm-常用参数"&gt;JVM 常用参数
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;-Xmx1024M 最大堆内存
-Xms1024M 初始化堆内存,正常和最大堆内存相同,减少动态改变的内存损
-Xmn384M 年轻代内存&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;-XX:+PrintGCDetails 打印 gc 信息,可参考 gc 的比例进行调优
-XX:+UseConcMarkSweepGC 老年代使用 cms,标记-清除算法会产生碎片
-XX:+UseParNewGC 年轻代使用并行收集器
-XX:SurvivorRatio=6&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="jvm-调优"&gt;JVM 调优
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;哪些情况会导致 Full GC&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;晋升失败（Survivor 区对象无法进入老年代）&lt;/li&gt;
&lt;li&gt;大对象直接进入老年代（Eden 无法容纳）&lt;/li&gt;
&lt;li&gt;空间分配担保失败（Minor GC 前老年代预估空间不足）&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;项目中哪些情况会导致 OOM&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;静态对象未释放，比如 &lt;code&gt;ThreadLocal&lt;/code&gt; 未调用 &lt;code&gt;remove&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;资源未关闭：数据库连接、网络连接、文件流未使用 &lt;code&gt;try-with-resources&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;一次性加载大量数据：如一次查出百万数据到 &lt;code&gt;List&lt;/code&gt;，或大文件全部加载到内存&lt;/li&gt;
&lt;li&gt;堆内存设置过小：&lt;code&gt;-Xmx&lt;/code&gt; 配置不合理，无法支撑运行负载&lt;/li&gt;
&lt;li&gt;线程池或线程使用不合理：无限制创建线程或队列无界，导致线程数暴涨&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="java-web"&gt;Java Web
&lt;/h2&gt;&lt;h3 id="过滤器filter和拦截器interceptor的区别"&gt;过滤器(Filter)和拦截器(Interceptor)的区别
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;执行时机&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​ Filter 是 Servlet 规范提供的，作用于 Servlet 容器层面，在&lt;code&gt;DispatcherServlet&lt;/code&gt;执行前就会执行&lt;/p&gt;
&lt;p&gt;​ Interceptor 是 Spring 框架提供的，作用于 Spring MVC 层，在&lt;code&gt;HandlerMapping&lt;/code&gt;匹配之后，Controller 执行前调用&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;实现方式&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;​ Filter 实现&lt;code&gt;javax.servlet.Filter&lt;/code&gt;接口，依赖&lt;code&gt;web.xml&lt;/code&gt;或注解进行注册&lt;/p&gt;
&lt;p&gt;​ Interceptor 实现&lt;code&gt;HandlerInterceptor&lt;/code&gt;接口，通过实现&lt;code&gt;WebMvcConfigurer&lt;/code&gt;的&lt;code&gt;addInterceptors()&lt;/code&gt;方法注册&lt;/p&gt;
&lt;p&gt;总结： 过滤器是 Servlet 规范定义的，依赖 Web 容器（如 Tomcat），在请求进入 Servlet 之前和响应发出之后工作，更底层; 拦截器是 Spring MVC 框架提供的，在请求进入 Controller 之前和视图渲染之后工作，更贴近业务&lt;/p&gt;
&lt;h2 id="常用框架"&gt;常用框架
&lt;/h2&gt;&lt;h3 id="谈谈你对-spring-的理解"&gt;谈谈你对 Spring 的理解
&lt;/h3&gt;&lt;h4 id="广义上"&gt;广义上
&lt;/h4&gt;&lt;p&gt;Spring 指的是 &lt;strong&gt;Spring 全家桶生态（Spring Ecosystem）&lt;/strong&gt;，不仅仅是一个框架，而是一整套企业级开发解决方案。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Spring Framework&lt;/strong&gt;（核心基础）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spring Boot&lt;/strong&gt;（快速开发、自动配置）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spring MVC&lt;/strong&gt;（Web 框架）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spring Data&lt;/strong&gt;（数据访问统一封装）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spring Cloud&lt;/strong&gt;（微服务治理）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Spring Security&lt;/strong&gt;（安全认证授权）&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="狭义上"&gt;狭义上
&lt;/h4&gt;&lt;p&gt;Spring 指的是 &lt;strong&gt;Spring Framework 核心容器&lt;/strong&gt;，主要解决的是对象如何创建、如何管理、如何协作的问题。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;IoC（控制反转）：对象的创建和管理交给 Spring 容器，通过 &lt;strong&gt;DI（依赖注入）&lt;/strong&gt; 完成对象装配，解耦对象之间的依赖关系。&lt;/li&gt;
&lt;li&gt;AOP（面向切面编程）：在不修改业务代码的情况下增强功能，如日志、事务、权限、监控，解耦横切逻辑。&lt;/li&gt;
&lt;li&gt;Bean 生命周期管理：Bean 的创建 → 初始化 → 使用 → 销毁，统一由容器管理。&lt;/li&gt;
&lt;li&gt;事件机制 &amp;amp; 扩展机制：支持事件发布监听模式（ApplicationEvent），提供强扩展能力（BeanPostProcessor）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="谈谈你对-aop-的理解"&gt;谈谈你对 AOP 的理解
&lt;/h3&gt;&lt;p&gt;AOP（面向切面编程）是一种在不修改业务代码的情况下，对日志、事务、权限等横切逻辑进行统一增强的编程思想，本质是通过切面和切点定义增强范围，并借助动态代理将增强逻辑织入目标方法中，实现解耦与复用。&lt;/p&gt;
&lt;h4 id="jdk-动态代理"&gt;JDK 动态代理
&lt;/h4&gt;&lt;p&gt;基于 Java 反射机制实现，要求目标类必须实现接口。通过 &lt;code&gt;InvocationHandler&lt;/code&gt; 对方法调用进行拦截，在方法执行前后织入增强逻辑。&lt;/p&gt;
&lt;h4 id="cglib-动态代理"&gt;CGLib 动态代理
&lt;/h4&gt;&lt;p&gt;基于继承实现代理，通过生成目标类的子类实现方法拦截，使用 &lt;code&gt;MethodInterceptor&lt;/code&gt; 进行增强处理。&lt;/p&gt;
&lt;p&gt;Spring AOP 默认优先使用 JDK 动态代理，只有在没有接口时才使用 CGLIB。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.evorsio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;java.lang.reflect.Proxy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * @author Evorsio
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * @since 2026/4/18
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JdkProxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;Student&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;study&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Zhangsan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Student&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;study&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;张三正在学习&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Zhangsan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zhangsan&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Zhangsan&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassLoader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;classLoader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zhangsan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClassLoader&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;?&amp;gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zhangsan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getInterfaces&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Student&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Student&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;newProxyInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;classLoader&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;interfaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;准备开始学习&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zhangsan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;学习完成&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;study&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;控制台输出&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\A&lt;/span&gt;dmin&lt;span class="se"&gt;\.&lt;/span&gt;jdks&lt;span class="se"&gt;\m&lt;/span&gt;s-17.0.18&lt;span class="se"&gt;\b&lt;/span&gt;in&lt;span class="se"&gt;\j&lt;/span&gt;ava.exe &lt;span class="s2"&gt;&amp;#34;-javaagent:D:\JetBrains\IntelliJ IDEA\lib\idea_rt.jar=60217&amp;#34;&lt;/span&gt; -Dfile.encoding&lt;span class="o"&gt;=&lt;/span&gt;UTF-8 -classpath D:&lt;span class="se"&gt;\J&lt;/span&gt;etBrainsProjects&lt;span class="se"&gt;\I&lt;/span&gt;deaProjects&lt;span class="se"&gt;\j&lt;/span&gt;ava-demo&lt;span class="se"&gt;\t&lt;/span&gt;arget&lt;span class="se"&gt;\c&lt;/span&gt;lasses com.evorsio.JdkProxy
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;准备开始学习
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;张三正在学习
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;学习完成
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Process finished with &lt;span class="nb"&gt;exit&lt;/span&gt; code &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="谈谈你对-ioc控制反转的理解"&gt;谈谈你对 IoC（控制反转）的理解
&lt;/h3&gt;&lt;p&gt;IoC（控制反转）是一种设计思想，将对象的创建和依赖关系的控制权交给容器管理，在 Spring 中通过依赖注入(DI)实现，从而实现对象之间的解耦和统一管理。&lt;/p&gt;
&lt;h3 id="依赖注入方式"&gt;依赖注入方式
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;字段注入：（&lt;code&gt;@Autowired&lt;/code&gt;&lt;strong&gt;Spring 提供的按类型注入&lt;/strong&gt;，&lt;code&gt;@Resource&lt;/code&gt;&lt;strong&gt;JDK 提供的按名称优先注入&lt;/strong&gt;。）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;构造器注入：（推荐）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Setter 方法注入&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="循环依赖问题和解决办法"&gt;循环依赖问题和解决办法
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Autowired&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Autowired&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="三个缓存"&gt;三个缓存
&lt;/h4&gt;&lt;p&gt;Spring 通过&lt;strong&gt;三级缓存机制&lt;/strong&gt;解决单例 Bean 的循环依赖：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;一级缓存（&lt;code&gt;singletonObjects = new ConcurrentHashMap(256)&lt;/code&gt;）：已初始化完成的 Bean&lt;/li&gt;
&lt;li&gt;二级缓存（&lt;code&gt;earlySingletonObjects = new ConcurrentHashMap(16)&lt;/code&gt;）：提前暴露的半成品 Bean 引用（可能是原始对象或代理对象）&lt;/li&gt;
&lt;li&gt;三级缓存（&lt;code&gt;singletonFactories = new HashMap(16)&lt;/code&gt;）：用于生成早期 Bean 的工厂对象（支持 AOP 代理提前暴露）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;流程&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Spring 创建 A 时，先从一级缓存 &lt;code&gt;singletonObjects&lt;/code&gt; 获取 A，未命中，则标记 A 为“正在创建”，进入创建流程。&lt;/li&gt;
&lt;li&gt;A 实例化（构造方法执行）后，Spring 不会直接暴露对象，而是将 &lt;code&gt;ObjectFactory(A)&lt;/code&gt; 放入三级缓存 &lt;code&gt;singletonFactories&lt;/code&gt;，用于后续生成 A 的早期引用。&lt;/li&gt;
&lt;li&gt;A 执行 &lt;code&gt;populateBean&lt;/code&gt; 进行属性填充时，发现依赖 B，触发 &lt;code&gt;getBean(B)&lt;/code&gt;，开始创建 B。&lt;/li&gt;
&lt;li&gt;B 创建流程与 A 一致：实例化后将 &lt;code&gt;ObjectFactory(B)&lt;/code&gt; 放入三级缓存，并开始属性填充。&lt;/li&gt;
&lt;li&gt;B 在 &lt;code&gt;populateBean&lt;/code&gt; 时发现依赖 A，此时触发获取 A：&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;一级缓存无&lt;/li&gt;
&lt;li&gt;二级缓存无&lt;/li&gt;
&lt;li&gt;三级缓存存在 A 的 ObjectFactory
Spring 调用 &lt;code&gt;getObject()&lt;/code&gt; 得到 A 的早期引用（可能是代理对象），并放入二级缓存 &lt;code&gt;earlySingletonObjects&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="6"&gt;
&lt;li&gt;B 完成初始化后进入一级缓存；A 随后完成属性填充与初始化，最终进入一级缓存，同时清理二级、三级缓存中的 A，循环依赖解决完成。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="四个方法"&gt;四个方法
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;&lt;code&gt;getBean()&lt;/code&gt; -&amp;gt; &lt;code&gt;doGetBean()&lt;/code&gt; -&amp;gt; &lt;code&gt;getSingleton()&lt;/code&gt; 从缓存中获取 Bean 对象。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;createBean()&lt;/code&gt; -&amp;gt; &lt;code&gt;doGetBean()&lt;/code&gt; -&amp;gt; &lt;code&gt;createBeanInstance()&lt;/code&gt; 创建 Bean 对象。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;populateBean()&lt;/code&gt;初始化 Bean 对象&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addSingleton()&lt;/code&gt; 将 Bean 对象保存到缓存中&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果需要循环依赖，可以手动开启 &lt;code&gt;spring.main.allow-circular-references=true&lt;/code&gt;，&lt;/p&gt;
&lt;p&gt;默认在 Spring Boot 2.6 之后是关闭的&lt;/p&gt;
&lt;h3 id="spring-常用注解"&gt;Spring 常用注解
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;IoC 相关注解: &lt;code&gt;@Component&lt;/code&gt; &lt;code&gt;@Autowired&lt;/code&gt; &lt;code&gt;@Configuration&lt;/code&gt; &lt;code&gt;@Bean&lt;/code&gt; &lt;code&gt;@Value&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AOP 相关注解: &lt;code&gt;@Transactional&lt;/code&gt; &lt;code&gt;@Aspect&lt;/code&gt; &lt;code&gt;@Before&lt;/code&gt; &lt;code&gt;@After&lt;/code&gt; &lt;code&gt;@AfterReturning&lt;/code&gt; &lt;code&gt;@AfterThrowing&lt;/code&gt; &lt;code&gt;@Around&lt;/code&gt; &lt;code&gt;@Pointcut&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="spring-bean-的作用域有哪些"&gt;Spring Bean 的作用域有哪些？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;singleton（单例，默认）&lt;/li&gt;
&lt;li&gt;prototype（原型）：每次获取都会创建一个新对象，不由容器统一管理完整生命周期。&lt;/li&gt;
&lt;li&gt;request（Web 环境）：每个 HTTP 请求创建一个 Bean，请求结束后销毁。&lt;/li&gt;
&lt;li&gt;session（Web 环境）：每个 HTTP Session 创建一个 Bean，Session 结束后销毁。&lt;/li&gt;
&lt;li&gt;application：整个 Web 应用生命周期内只有一个 Bean，类似 ServletContext 级别。&lt;/li&gt;
&lt;li&gt;websocket：每个 WebSocket 会话对应一个 Bean。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="spring-bean-的生命周期有哪些"&gt;Spring Bean 的生命周期有哪些？
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.evorsio.springdemo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * @author Evorsio
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * @since 2026/4/18
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA: 使用userA对象: User{&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;username=&amp;#39;&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;\&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sc"&gt;&amp;#39;}&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;setUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA: 调用setter方法,对username属性进行赋值&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA: 调用无参构造&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA: 调用有参构造&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA: 调用初始化方法,对userA对象进行初始化&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA: 调用销毁方法&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.evorsio.springdemo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;org.jspecify.annotations.Nullable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;org.springframework.beans.BeansException&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;org.springframework.beans.factory.config.BeanPostProcessor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/**
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * @author Evorsio
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * @since 2026/4/18
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyBeanPostProcessor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BeanPostProcessor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Nullable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;postProcessBeforeInitialization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BeansException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;myBeanPostProcessor: 对&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;对象初始化前执行的操作&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BeanPostProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;postProcessBeforeInitialization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Nullable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;postProcessAfterInitialization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;throws&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BeansException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;myBeanPostProcessor: 对&amp;#34;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;对象初始化后执行的操作&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BeanPostProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;postProcessAfterInitialization&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;beanName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;beans&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.springframework.org/schema/beans&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;xmlns:xsi=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.w3.org/2001/XMLSchema-instance&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;xsi:schemaLocation=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;com.evorsio.springdemo.User&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;init-method=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;init&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;destroy-method=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;destroy&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;property&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;username&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;zhangsan&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;/bean&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;bean&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;myBeanPostProcessor&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;com.evorsio.springdemo.MyBeanPostProcessor&amp;#34;&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/beans&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;com.evorsio.springdemo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;org.springframework.context.support.ClassPathXmlApplicationContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SpringDemoApplication&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;static&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassPathXmlApplicationContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ClassPathXmlApplicationContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;spring.xml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;userA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;userA&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userA&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;流程&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;C:&lt;span class="se"&gt;\U&lt;/span&gt;sers&lt;span class="se"&gt;\A&lt;/span&gt;dmin&lt;span class="se"&gt;\.&lt;/span&gt;jdks&lt;span class="se"&gt;\m&lt;/span&gt;s-17.0.18&lt;span class="se"&gt;\b&lt;/span&gt;in&lt;span class="se"&gt;\j&lt;/span&gt;ava.exe ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;com.evorsio.springdemo.SpringDemoApplication
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;1. userA: 调用无参构造
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2. userA: 调用setter方法,对username属性进行赋值
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;3. myBeanPostProcessor: 对userA对象初始化前执行的操作
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;4. userA: 调用初始化方法,对userA对象进行初始化
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5. myBeanPostProcessor: 对userA对象初始化后执行的操作
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;6. userA: 使用userA对象: User&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;username&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;zhangsan&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;7. userA: 调用销毁方法
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Process finished with &lt;span class="nb"&gt;exit&lt;/span&gt; code &lt;span class="m"&gt;0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="spring-cloud"&gt;Spring Cloud
&lt;/h2&gt;&lt;h3 id="项目中使用了哪些-spring-cloud-组件"&gt;项目中使用了哪些 Spring Cloud 组件？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Nacos 注册中心 + 配置中心&lt;/li&gt;
&lt;li&gt;OpenFeign 声明式远程调用&lt;/li&gt;
&lt;li&gt;Spring Cloud Gateway 全局网关&lt;/li&gt;
&lt;li&gt;Sentinel 限流熔断降级&lt;/li&gt;
&lt;li&gt;LoadBalancer 负载均衡&lt;/li&gt;
&lt;li&gt;Sleuth 链路追踪( Spring Boot 3 中被移除 ，改用 Micrometer Tracing + OpenTelemtry ) + Zipkin 进行链路可视化。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="open-feign-和-feign-的区别"&gt;Open Feign 和 Feign 的区别
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Feign 是 Netflix 早期的声明式 HTTP 客户端，不支持 Spring MVC 注解，不再维护。&lt;/li&gt;
&lt;li&gt;OpenFeign 是 Spring Cloud 对 Feign 的增强版本，深度集成了 Spring 生态，支持 Spring MVC 注解、服务发现、负载均衡和熔断机制，是目前微服务中主流的远程调用方式，社区依然活跃。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="实际开发过程中-openfeign-请求头丢失的问题"&gt;实际开发过程中 OpenFeign 请求头丢失的问题
&lt;/h3&gt;&lt;p&gt;消费方通过 OpenFeign 调用生产方接口时，Feign 底层会&lt;strong&gt;重新发起一个新的 HTTP 请求&lt;/strong&gt;，而不是在原请求基础上进行转发，原始请求中的 Header（如 Token、用户信息、TraceId 等）不会自动携带到新的 Feign 请求中，导致请求头信息丢失或不一致。&lt;/p&gt;
&lt;p&gt;Spring 中的请求上下文是通过 &lt;strong&gt;RequestContextHolder&lt;/strong&gt;（基于 ThreadLocal）存储的，在 Feign 调用过程中不会自动传播，因此需要通过 RequestInterceptor 手动从 &lt;strong&gt;RequestContextHolder&lt;/strong&gt; 获取原始请求 Header 并进行透传。&lt;/p&gt;
&lt;p&gt;基本用法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;导入依赖: spring-cloud-starter-alibaba-nacos-discovery&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;配置 Nacos 地址: &lt;code&gt;spring.cloud.nacos.discovery.server-addr = localhost:8848&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@EnableFeignClients&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OrderApplication&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;//...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@FeignClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;stock-nacos&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StockFeignFallback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;StockFeignClient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@GetMapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;/stock/reduce&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;reduceStock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;StockFeignFallback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;implements&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;StockFeignClient&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nd"&gt;@Override&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;reduceStock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;库存服务降级，当前不可用&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="项目中哪些场景使用到了-spring-cloud-gateway-的功能"&gt;项目中哪些场景使用到了 Spring Cloud Gateway 的功能？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;项目中将网关作为一个独立的功能进行部署，基于路径断言将请求通过负载均衡的方式进行分发。&lt;/li&gt;
&lt;li&gt;全局的跨域问题处理（由于浏览器的同源策略导致），使用 &lt;code&gt;spring.cloud.gateway.globalcors.cors-configurations.[/**].allowed-origins=*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;通过实现网关的全局过滤进行身份验证&lt;/li&gt;
&lt;li&gt;配置限流&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;组成：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Route（路由）: 定义请求转发规则&lt;/li&gt;
&lt;li&gt;Predicate（断言）: 判断请求是否匹配（路径、Header、参数）&lt;/li&gt;
&lt;li&gt;Filter（过滤器）: 请求前后处理逻辑（鉴权、日志、限流）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="有了-nginx-为什么还需要网关呢"&gt;有了 Nginx 为什么还需要网关呢？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Nginx 主要负责：反向代理，静态资源托管，负载均衡，SSL/TLS 等，只管“流量怎么走”，不关心“业务是什么”。&lt;/li&gt;
&lt;li&gt;Spring Cloud Gateway 负责：统一 API 入口，路由转发，JWT 鉴权 / 登录校验等，关注“业务请求如何被处理”，服务于微服务。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="请求过来之后如何进行流量控制"&gt;请求过来之后如何进行流量控制？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;客户端削峰填谷： 前端限流（按钮置灰），请求缓存&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;网关层限流：RequestRateLimiter&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;spring&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;cloud&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;gateway&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;order-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;lb://order-service&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;predicates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;Path=/order/**&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# =========================&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 限流 RequestRateLimiter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# =========================&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;RequestRateLimiter&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;redis-rate-limiter.replenishRate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 每秒放入令牌数（QPS）&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;redis-rate-limiter.burstCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# 最大突发流量&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;key-resolver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;#{@ipKeyResolver}&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;应用层限流： Sentinel（ 限制 QPS 或者线程数 ）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@SentinelResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;getOrder&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;blockHandler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;blockHandlerMethod&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;fallbackMethod&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;getOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;正常业务逻辑&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;blockHandlerMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BlockException&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;请求过多，请稍后重试&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fallbackMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;系统异常，已降级处理&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;服务熔断与降级：Open Feign 熔断降级&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="nacos-作为服务注册和配置中心的原理"&gt;Nacos 作为服务注册和配置中心的原理
&lt;/h3&gt;&lt;h4 id="启动参数"&gt;启动参数
&lt;/h4&gt;&lt;p&gt;-Dnacos.standalone=true&lt;/p&gt;
&lt;h4 id="服务注册"&gt;服务注册
&lt;/h4&gt;&lt;p&gt;客户端（服务提供者）启动后：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;向 Nacos Server 发送注册请求&lt;/li&gt;
&lt;li&gt;请求内容包含：serviceName、ip、port、metadata&lt;/li&gt;
&lt;li&gt;数据通过 HTTP REST 接口发送&lt;/li&gt;
&lt;li&gt;Server 使用 request 对象接收参数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;注册完成后：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;服务实例被存入 Nacos 内存注册表&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="服务健康检测"&gt;服务健康检测
&lt;/h4&gt;&lt;p&gt;Nacos Server 会定时执行健康检查任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;检查所有注册实例的心跳时间&lt;/li&gt;
&lt;li&gt;判断实例是否存活&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;判断规则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前时间 - 最后心跳时间 &amp;gt; 15 秒 → 标记为不健康&lt;/li&gt;
&lt;li&gt;当前时间 - 最后心跳时间 &amp;gt; 30 秒 → 从注册表移除实例&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="服务心跳任务client"&gt;服务心跳任务（Client）
&lt;/h4&gt;&lt;p&gt;客户端在服务注册后会启动心跳任务：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每 5 秒发送一次心跳请求&lt;/li&gt;
&lt;li&gt;请求接口：beat（REST）&lt;/li&gt;
&lt;li&gt;通过定时 + 延迟任务实现&lt;/li&gt;
&lt;li&gt;作用：告诉 Server 当前服务仍然存活&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="客户端服务发现"&gt;客户端服务发现
&lt;/h4&gt;&lt;p&gt;服务消费者（Nacos Client）调用服务时：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;向 Nacos Server 发送 REST 请求&lt;/li&gt;
&lt;li&gt;获取服务实例列表&lt;/li&gt;
&lt;li&gt;将结果缓存到本地（serviceInfoMap）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;同时：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在本地启动定时任务&lt;/li&gt;
&lt;li&gt;周期性拉取服务端最新注册表&lt;/li&gt;
&lt;li&gt;更新本地缓存&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="nacos-1x-和-2x-的区别"&gt;Nacos 1.x 和 2.x 的区别
&lt;/h3&gt;&lt;p&gt;1.x 基于 HTTP + 定时任务（心跳、轮询）；2.x 引入 gRPC 长连接 + 事件驱动模型，支持服务变更实时推送。&lt;/p&gt;
&lt;h3 id="除了-nacos-还有那些注册中心"&gt;除了 Nacos 还有那些注册中心
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;Eureka（Netflix）：AP（高可用），去中心化设计（Peer-to-Peer，无主节点，节点对等，数据通过复制实现同步）。&lt;/li&gt;
&lt;li&gt;Zookeeper（Apache）：CP（强一致），Leader 选举机制（集群选举主节点负责协调，保证一致性）。&lt;/li&gt;
&lt;li&gt;Nacos：AP/CP 可切换，默认 AP；同时支持注册中心 + 配置中心，采用临时实例（心跳）+ 长轮询/推送机制实现服务发现。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="mysql"&gt;MySQL
&lt;/h2&gt;&lt;h3 id="如何进行-sql-优化"&gt;如何进行 SQL 优化
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;慢查询定位：开启慢查询日志定位慢 SQL，通常 0.5 秒（默认 10 秒）开始，但应该根据业务类型和性能要求调整。&lt;/li&gt;
&lt;li&gt;explain 指令查看执行计划：
&lt;ul&gt;
&lt;li&gt;id: SQL 执行的顺序与层级, id 相同：从上到下执行, id 不同：数字大的先执行（子查询）。&lt;/li&gt;
&lt;li&gt;type: 查询类型一旦为 ALL（全表扫描）则必须优化，合理取值 ref（普通索引查询）,eq_ref（唯一索引 join）,range（范围查询）,index（对整个索引进行扫描）。&lt;/li&gt;
&lt;li&gt;key：真正使用到的索引&lt;/li&gt;
&lt;li&gt;key_len：索引使用的长度&lt;/li&gt;
&lt;li&gt;rows：为了获取结果所需要扫描的行数&lt;/li&gt;
&lt;li&gt;extra：主要用于分析分组和排序操作，using index（使用覆盖索引，不需要回表查询数据行，性能好），using where（where 的条件没有用到索引），using filesort（使用磁盘排序），using index condition（使用索引下推优化，在存储引擎层提前过滤数据，减少回表次数）。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;可以通过 &lt;code&gt;key&lt;/code&gt; 和 &lt;code&gt;key_len&lt;/code&gt; 判断是否命中了索引以及索引是否被完整使用，从而发现索引是否失效；通过 &lt;code&gt;type&lt;/code&gt; 判断 SQL 的访问方式和扫描类型，评估是否存在全表扫描或全索引扫描等优化空间；再结合 &lt;code&gt;extra&lt;/code&gt; 字段判断执行细节，例如 &lt;code&gt;Using index&lt;/code&gt; 表示覆盖索引无需回表，&lt;code&gt;Using where&lt;/code&gt; 表示条件可能未充分利用索引，&lt;code&gt;Using filesort&lt;/code&gt; 表示排序或分组未走索引需要优化，整体通过这些字段综合判断 SQL 是否需要优化以及优化方向。&lt;/p&gt;
&lt;h3 id="合理创建索引"&gt;合理创建索引
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;表数据量达到一定规模（ 15 万以上），才具备明显优化意义&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;考虑性价比更高的复合索引设计&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;尽量让查询走覆盖索引以减少回表&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;需要重点关注索引失效的场景：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;未遵循最左匹配原则&lt;/li&gt;
&lt;li&gt;模糊查询中 &lt;code&gt;%&lt;/code&gt; 在左边&lt;/li&gt;
&lt;li&gt;对索引字段使用函数或发生类型转换&lt;/li&gt;
&lt;li&gt;范围查询导致右边索引失效&lt;/li&gt;
&lt;li&gt;以及 &lt;code&gt;is not null&lt;/code&gt; 等导致扫描范围过大的情况&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在关联查询中，应尽量选择小表作为驱动表，并为关联字段创建索引以提升 join 查询效率。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;编写 SQL 语句时避免使用 select *，防止全表扫描或多余回表查询。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;表关联查询优先使用 inner join，避免不必要的 left/right join，如需使用也应以小表为驱动表。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;排序字段尽量保持一致的排序规则（避免一列升序一列降序），以便索引生效。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;建表时结合字段内容选择合适类型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数值：&lt;code&gt;TINYINT&lt;/code&gt;：很小的整数（状态位、标志位），&lt;code&gt;INT&lt;/code&gt;：常用整数（默认选择），&lt;code&gt;BIGINT&lt;/code&gt;：大数据量 ID（如雪花 ID）&lt;/li&gt;
&lt;li&gt;字符串：&lt;code&gt;CHAR(n)&lt;/code&gt;：长度固定（如手机号、身份证），&lt;code&gt;VARCHAR(n)&lt;/code&gt;：长度可变（最常用），&lt;code&gt;TEXT&lt;/code&gt;：大文本（不建议频繁索引）&lt;/li&gt;
&lt;li&gt;价格：不要用 FLOAT / DOUBLE（会有精度问题）推荐：&lt;code&gt;DECIMAL(m,n)&lt;/code&gt;，m：总位数 n：小数位数&lt;/li&gt;
&lt;li&gt;时间：用于时间记录（创建时间、更新时间等）&lt;code&gt;DATE&lt;/code&gt;：日期（2026-04-19），&lt;code&gt;DATETIME&lt;/code&gt;：日期+时间（推荐），&lt;code&gt;TIMESTAMP&lt;/code&gt;：时间戳（带时区转换）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="b-tree-和-btree-的区别"&gt;B-Tree 和 B+Tree 的区别
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;B-Tree：所有节点（非叶子 + 叶子）都存储数据，每个节点既存 key 也存 data。&lt;/li&gt;
&lt;li&gt;B+Tree: 只有叶子节点存数据，非叶子节点只存索引（key）。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="btree-的优点"&gt;B+Tree 的优点
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;B+Tree 数据全部存储在叶子节点，非叶子节点只存索引，因此单个节点可以容纳更多的索引项，从而降低树的高度，减少磁盘 IO 次数，提升查询效率。&lt;/li&gt;
&lt;li&gt;B+Tree 叶子节点之间通过双向指针相连，可以非常高效地进行&lt;strong&gt;范围查询和顺序遍历&lt;/strong&gt;，可以直接在叶子层顺序向前或向后扫描，从而显著减少磁盘 IO，提高查询性能。同时双向结构还支持反向遍历，进一步增强查询灵活性。&lt;/li&gt;
&lt;li&gt;B+Tree 查询路径固定，每次查询都必须从根节点一路访问到叶子节点，每一层只进行一次节点匹配，因此整体查询次数是稳定且可预测的。&lt;/li&gt;
&lt;li&gt;B+Tree 通常在 3 层结构下就可以存储约 2000 万级别的数据。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;备注&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;InnoDB 一个页（page）默认大小：&lt;strong&gt;16KB = 16384 bytes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;非叶子节点存只存索引 key（BIGINT = 8 bytes）和指针（通常 6-8 bytes）&lt;/p&gt;
&lt;p&gt;每个节点能存多少“分支”：16384 / 16 ≈ 1000 个指针&lt;/p&gt;
&lt;p&gt;三层 B+Tree 推导：1000 × 1000 × 16（ 一行 ≈ 1KB）≈ 2000 万&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h3 id="什么是回表"&gt;什么是回表
&lt;/h3&gt;&lt;p&gt;通过二级索引（非聚簇索引）找到主键后，还需要再回到主键索引（聚簇索引）中查询完整数据行的过程。&lt;/p&gt;
&lt;h3 id="select--查询一定会回表吗"&gt;Select * 查询一定会回表吗？
&lt;/h3&gt;&lt;p&gt;不一定会回表，如果查询条件是主键索引（聚簇索引），例如 &lt;code&gt;where id = ?&lt;/code&gt;，MySQL 会直接在聚簇索引中找到整行数据，因此不会发生回表；只有在使用二级索引查询且无法覆盖所有字段时，才会发生回表。&lt;/p&gt;
&lt;h3 id="mysql-深分页超大分页问题如何优化"&gt;MySQL 深分页（超大分页）问题如何优化？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;游标分页：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;last_id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;通过记录上一页最后一条数据的主键（如 &lt;code&gt;last_id&lt;/code&gt;），作为下一页查询的起点，利用索引有序性进行范围查询。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;延迟关联（子查询优化）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ORDER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIMIT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;ON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;先通过子查询在索引中只查询主键（小结果集），再通过主键与原表关联回表获取完整数据，从而减少大范围扫描带来的性能损耗。&lt;/p&gt;
&lt;h3 id="什么是索引下推原理"&gt;什么是索引下推，原理？
&lt;/h3&gt;&lt;p&gt;索引下推是 MySQL（InnoDB）的一种优化机制，核心思想是：在存储引擎层就先用索引过滤数据，减少回表次数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LIKE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;A%&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;先用索引（如 name）定位数据范围&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在&lt;strong&gt;索引层同时判断 age = 20&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;只把满足条件的记录回表查询完整数据&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;减少无效回表次数，提高性能&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="innodb-和-myisam-的区别"&gt;InnoDB 和 MyISAM 的区别
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;对比项&lt;/th&gt;
 &lt;th&gt;InnoDB&lt;/th&gt;
 &lt;th&gt;MyISAM&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;事务&lt;/td&gt;
 &lt;td&gt;✔ 支持（ACID）&lt;/td&gt;
 &lt;td&gt;❌ 不支持&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;锁机制&lt;/td&gt;
 &lt;td&gt;行级锁&lt;/td&gt;
 &lt;td&gt;表级锁&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;外键&lt;/td&gt;
 &lt;td&gt;✔ 支持&lt;/td&gt;
 &lt;td&gt;❌ 不支持&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;崩溃恢复&lt;/td&gt;
 &lt;td&gt;✔ 支持（redo log）&lt;/td&gt;
 &lt;td&gt;❌ 不支持&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;索引结构&lt;/td&gt;
 &lt;td&gt;聚簇索引&lt;/td&gt;
 &lt;td&gt;非聚簇索引&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;查询性能&lt;/td&gt;
 &lt;td&gt;稍慢（但稳定）&lt;/td&gt;
 &lt;td&gt;快（读多场景）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="数据库三大范式"&gt;数据库三大范式
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;第一范式（1NF）：字段必须是&lt;strong&gt;不可再分的原子值&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;第二范式（2NF）：每个非主键字段必须&lt;strong&gt;完全依赖主键&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;第三范式（3NF）：非主键字段之间不能传递依赖&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="事务特性acid"&gt;事务特性（ACID）
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;A - Atomicity（原子性）：事务中的操作要么全部执行成功，要么全部失败回滚，通过 &lt;code&gt;undo log&lt;/code&gt; 保证回滚能力。&lt;/li&gt;
&lt;li&gt;C - Consistency（一致性）：事务执行前后，数据必须从一个合法状态转换到另一个合法状态，保证数据符合业务规则。&lt;/li&gt;
&lt;li&gt;I - Isolation（隔离性）：多个事务并发执行时互不干扰，通过 &lt;code&gt;锁机制（排他锁等）&lt;/code&gt; 和 &lt;code&gt;MVCC&lt;/code&gt; 保证并发隔离。&lt;/li&gt;
&lt;li&gt;D - Durability（持久性）：事务一旦提交，数据就会永久保存，即使系统崩溃也不会丢失，通过 &lt;code&gt;redo log&lt;/code&gt; 保证。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="事务隔离级别和解决的问题"&gt;事务隔离级别和解决的问题
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;读未提交（Read Uncommitted）&lt;/strong&gt;：不解决任何并发问题，可能出现脏读、不可重复读、幻读。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;读已提交（Read Committed）&lt;/strong&gt;：（Oracle 默认）解决脏读，但仍可能出现不可重复读和幻读，适合银行业务对资金实时业务的要求。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;可重复读（Repeatable Read）&lt;/strong&gt;（MySQL 默认）：解决脏读和不可重复读，通过 MVCC + 间隙锁在一定程度上避免幻读，适合互联网电商业务“强一致读场景”。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;串行化（Serializable）&lt;/strong&gt;：完全解决脏读、不可重复读和幻读，通过强制事务串行执行实现最高隔离级别，但并发性能最差。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="分布式事务"&gt;分布式事务
&lt;/h3&gt;&lt;p&gt;分布式事务是指跨多个服务或数据库的事务一致性问题，无法依赖本地事务实现，常见解决方案是基于最终一致性的方案，如消息队列和 Seata。&lt;/p&gt;
&lt;h3 id="长事务问题"&gt;长事务问题
&lt;/h3&gt;&lt;p&gt;事务执行时间过长，持有锁或版本过久未释放的情况&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;占用数据库连接资源&lt;/li&gt;
&lt;li&gt;锁持有时间长，导致阻塞和死锁概率增加&lt;/li&gt;
&lt;li&gt;undo log / MVCC 版本堆积，影响性能&lt;/li&gt;
&lt;li&gt;可能导致数据库性能整体下降&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;优化思路：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;拆分大事务（拆成多个小事务）&lt;/li&gt;
&lt;li&gt;避免事务中包含远程调用&lt;/li&gt;
&lt;li&gt;减少锁持有时间&lt;/li&gt;
&lt;li&gt;异步化处理非核心逻辑&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="mysql-的-mvcc-会导致表膨胀吗"&gt;MySQL 的 MVCC 会导致表膨胀吗？
&lt;/h3&gt;&lt;p&gt;MySQL 的 MVCC 通过 undo log 记录数据的历史版本，并结合 Read View 判断可见性，同时依赖 purge 线程在没有活跃事务引用旧版本时清理 undo log，从而避免历史版本无限增长导致的空间膨胀。&lt;/p&gt;
&lt;p&gt;此外，对于&lt;strong&gt;删除操作&lt;/strong&gt;，InnoDB 并不会立即物理删除数据，而是先做“标记删除”，旧版本仍通过 undo log 保留；当 purge 线程确认没有事务再引用该版本后，才会真正物理删除该记录，并将这块空间&lt;strong&gt;标记为可复用（供后续插入使用）&lt;/strong&gt;，从而避免空间浪费。&lt;/p&gt;
&lt;p&gt;但如果存在长事务，会导致旧版本无法被清理，进而造成 undo log 堆积和空间占用增加。&lt;/p&gt;
&lt;h3 id="mysql-中的锁"&gt;MySQL 中的锁
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;锁性质&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;悲观锁：假设会发生冲突，先加锁再操作，通过数据库锁机制实现（如 &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt;），适用于写多、冲突概率高的场景。&lt;/li&gt;
&lt;li&gt;乐观锁：假设不会冲突，提交时再检查，通常通过版本号（version）或 CAS 实现，适用于读多写少的场景。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start="2"&gt;
&lt;li&gt;
&lt;p&gt;锁粒度&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;表级锁：锁整张表，开销小，实现简单，但并发性能低，常见于 MyISAM 引擎。&lt;/li&gt;
&lt;li&gt;行级锁：锁具体某一行数据，并发能力强，粒度最小，InnoDB 默认使用（提升并发性能）。&lt;/li&gt;
&lt;li&gt;意向锁（InnoDB 特有）：是一种“表级的标记锁”，用于表示某个事务&lt;strong&gt;即将对某些行加锁&lt;/strong&gt;，不直接锁数据，只是“声明意图”，避免表锁与行锁冲突，提高加锁效率。
&lt;ol&gt;
&lt;li&gt;意向共享锁（IS）：表示“事务准备在某些行上加共享锁”，读操作前会加。&lt;/li&gt;
&lt;li&gt;意向排他锁（IX）：表示“事务准备在某些行上加排他锁”，写操作前会加。&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;锁类型&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;共享锁（S 锁）：读锁，多个事务可以同时持有，读读不冲突，但读写冲突。&lt;/li&gt;
&lt;li&gt;排他锁（X 锁）：写锁，同一时间只能一个事务持有，写写、读写都会冲突。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="如何进行数据库数据迁移"&gt;如何进行数据库数据迁移？
&lt;/h3&gt;&lt;h4 id="迁移方案"&gt;迁移方案
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;停机一次性迁移：停止业务写入，进行全量数据导出（mysqldump / pg_dump），导入新库后切换应用连接，适用于小数据量或可接受停机的场景。&lt;/li&gt;
&lt;li&gt;在线分批次迁移：采用“全量 + 增量”方式，先迁移历史数据，再通过 binlog/CDC（如 Canal）同步增量数据，最后灰度切换流量，适用于大规模或不能停机的系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="迁移过程可能导致的问题"&gt;迁移过程可能导致的问题
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;数据一致性问题：迁移期间仍有写入，导致新旧库数据不一致或延迟同步问题。&lt;/li&gt;
&lt;li&gt;应用兼容性问题：新旧库表结构或 SQL 语法不一致，导致接口报错或查询异常。&lt;/li&gt;
&lt;li&gt;性能抖动问题：全量导入或 binlog 同步造成数据库 IO 和网络压力上升，影响线上业务。&lt;/li&gt;
&lt;li&gt;回滚困难问题：若未保留旧库或未做双写，切换后出现问题难以快速回退。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="如何减少迁移过程对用户体验的影响"&gt;如何减少迁移过程对用户体验的影响
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;兼容性测试：在迁移前进行 SQL 兼容性、表结构、接口回归测试，确保新旧库在读写行为上一致。&lt;/li&gt;
&lt;li&gt;采用“全量+增量“的同步方案：先进行历史数据全量迁移，再通过 binlog / CDC（如 Canal）同步增量数据，保证业务不中断。&lt;/li&gt;
&lt;li&gt;设计灰度切换：通过按用户比例或业务模块逐步切换流量到新库，降低整体切换风险。&lt;/li&gt;
&lt;li&gt;监控与回滚预案：全程监控延迟、错误率、数据一致性等指标，一旦异常可快速切回旧库，保证业务可恢复性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;一般会做全量迁移，再做增量同步，分阶段灰度切换流量，监控数据一致性和业务指标，遇到异常可快速回滚，尽量把对用户的影响降至最低。&lt;/p&gt;
&lt;h3 id="业务每天新增-1000-万笔订单某天需要导出应该如何做"&gt;业务每天新增 1000 万笔订单，某天需要导出应该如何做？
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;按条件分批导出：按 &lt;strong&gt;时间 / ID / 分片键&lt;/strong&gt; 将数据拆分成多个区间分批查询导出，避免一次性全表扫描导致数据库压力过大。&lt;/li&gt;
&lt;li&gt;分布式并行导出：将导出任务拆分为多个子任务，通过多线程或分布式任务执行（按 ID hash / 时间分片），提升导出效率。&lt;/li&gt;
&lt;li&gt;异步任务执行：将导出操作放入后台任务系统（如 MQ / XXL-Job），避免阻塞请求线程，提升系统可用性。&lt;/li&gt;
&lt;li&gt;分页批量拉取数据：采用 &lt;strong&gt;limit + 游标（last_id）&lt;/strong&gt; 或按范围分页方式逐批查询数据，避免 OFFSET 深分页性能问题。&lt;/li&gt;
&lt;li&gt;流式写文件：使用流式读取 + 流式写出（如 BufferedWriter / JDBC fetch size），边查询边写入文件，避免内存占用过高。&lt;/li&gt;
&lt;li&gt;上传 S3 对象存储：导出完成后将文件上传到对象存储（如 S3 / OSS），提供下载链接，避免本地磁盘压力并支持高并发下载。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;对于大订单导出，通常采用异步任务+分页批处理+流式写出+对象存储的组合，用户点击导出，只是在后端提交异步任务，后台消息队列异步消费，数据库分批拉取避免全表扫描，使用游标或 id 分页，分批流式写出文件，不放在内存中而是写到对象存储服务（OSS）中供用户下载。&lt;/p&gt;
&lt;p&gt;导入具体步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;将业务数据预处理为 &lt;strong&gt;CSV / TSV 等标准格式文件&lt;/strong&gt;，保证字段顺序与目标表结构一致。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 SCP / FTP / OSS 下载等方式，将数据文件传输到数据库所在机器本地磁盘，提高导入性能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在导入前暂时禁用二级索引或约束，减少索引维护开销，提高导入速度。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;DISABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;KEYS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;#&lt;/span&gt;&lt;span class="err"&gt;导入完成后再恢复：&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ENABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;KEYS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用 MySQL 高效导入命令进行快速加载：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;LOAD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;DATA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;INFILE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/path/file.csv&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;INTO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TABLE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;FIELDS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TERMINATED&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;,&amp;#39;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;LINES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TERMINATED&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;BY&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;\n&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;导入完成后重新创建索引（或恢复索引），并进行数据校验（行数对比 / checksum）确保数据一致性。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="redis"&gt;Redis
&lt;/h2&gt;&lt;h3 id="redis-中的基本类型及应用场景"&gt;Redis 中的基本类型及应用场景
&lt;/h3&gt;&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;数据类型&lt;/th&gt;
 &lt;th&gt;底层数据结构&lt;/th&gt;
 &lt;th&gt;特点&lt;/th&gt;
 &lt;th&gt;常见应用场景&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;String&lt;/td&gt;
 &lt;td&gt;SDS（简单动态字符串）&lt;/td&gt;
 &lt;td&gt;O(1) 访问、可扩展、支持二进制安全&lt;/td&gt;
 &lt;td&gt;缓存、计数器、分布式锁、Token&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;SET user:1 &amp;quot;json&amp;quot;&lt;/code&gt; / &lt;code&gt;INCR pv&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Hash&lt;/td&gt;
 &lt;td&gt;ziplist / hashtable（小对象 ziplist，大对象 hashtable）&lt;/td&gt;
 &lt;td&gt;适合存对象，节省内存&lt;/td&gt;
 &lt;td&gt;用户信息、订单对象&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;HSET user:1 name Tom&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;List&lt;/td&gt;
 &lt;td&gt;quicklist（ziplist + linkedlist（双向链表））&lt;/td&gt;
 &lt;td&gt;双端队列结构，支持阻塞&lt;/td&gt;
 &lt;td&gt;消息队列、最新列表&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;LPUSH queue order1&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Set&lt;/td&gt;
 &lt;td&gt;hashtable（整数集合 intset / hashtable）&lt;/td&gt;
 &lt;td&gt;无序唯一、支持集合运算&lt;/td&gt;
 &lt;td&gt;去重、共同好友&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;SADD tags java redis&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ZSet&lt;/td&gt;
 &lt;td&gt;skiplist（跳表） + hashtable&lt;/td&gt;
 &lt;td&gt;有序、支持范围查询和排序&lt;/td&gt;
 &lt;td&gt;排行榜、热度排序&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ZADD rank 100 user1&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;BitMap&lt;/td&gt;
 &lt;td&gt;String（位操作，本质是 bit 数组）&lt;/td&gt;
 &lt;td&gt;极省内存，高效状态标记&lt;/td&gt;
 &lt;td&gt;签到、活跃用户统计&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;SETBIT sign 1 1&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Pub/Sub&lt;/td&gt;
 &lt;td&gt;事件驱动（channel + dict 结构）&lt;/td&gt;
 &lt;td&gt;消息广播，实时通知&lt;/td&gt;
 &lt;td&gt;聊天室、系统通知&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;PUBLISH msg &amp;quot;hi&amp;quot;&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="跳表skiplist的说明"&gt;跳表（SkipList）的说明
&lt;/h3&gt;&lt;p&gt;跳表（SkipList）是一种&lt;strong&gt;基于有序链表 + 多级索引&lt;/strong&gt;的数据结构，通过“空间换时间”来实现类似&lt;strong&gt;二分查找&lt;/strong&gt;的效率。&lt;/p&gt;
&lt;h4 id="为什么不用红黑树"&gt;为什么不用红黑树？
&lt;/h4&gt;&lt;ol&gt;
&lt;li&gt;红黑树：中序遍历较复杂，跳表：链表天然顺序结构，范围查询非常快。&lt;/li&gt;
&lt;li&gt;不需要复杂旋转（红黑树需要旋转维护平衡），更容易维护和调试。&lt;/li&gt;
&lt;li&gt;局部修改，不需要大范围结构调整。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="redis-是单线程为什么会快呢"&gt;Redis 是单线程为什么会快呢？
&lt;/h3&gt;&lt;p&gt;Redis 只是命令处理模型是单线程的，避免了锁竞争和线程切换开销，同时基于 I/O 多路复用（epoll）实现高并发连接处理，所有数据在内存中操作，并配合高度优化的数据结构，使得单线程也能实现极高吞吐；在 Redis 6 之后引入 I/O 多线程用于提升网络读写性能，但核心命令执行仍然是单线程。&lt;/p&gt;
&lt;h3 id="谈谈你对-io-多路复用的理解"&gt;谈谈你对 I/O 多路复用的理解
&lt;/h3&gt;&lt;p&gt;I/O 多路复用是一种通过一个线程监听多个 socket 的机制，利用 epoll 等系统调用在内核层管理连接状态，只处理就绪的 I/O 事件，从而避免线程阻塞和频繁创建线程的问题，提高系统并发能力。&lt;/p&gt;
&lt;h3 id="io-多路复用实现的三种方式"&gt;I/O 多路复用实现的三种方式
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;select：最早的 I/O 多路复用实现，通过&lt;strong&gt;轮询所有 fd&lt;/strong&gt;检查状态（fd 数量有限（默认 1024））。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;轮询&lt;/li&gt;
&lt;li&gt;有 fd（文件描述符）大小限制&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;poll：是 select 的改进版，去掉了 fd 数量限制，同样需要&lt;strong&gt;遍历所有 fd&lt;/strong&gt;（仍然是 O(n) 轮询）。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;仍是轮询&lt;/li&gt;
&lt;li&gt;没有 fd 限制&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;epoll：事件驱动模型，注册 fd 到内核，等待事件发生，返回“就绪 fd 列表”。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;事件驱动&lt;/li&gt;
&lt;li&gt;高性能&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="操作系统用户态和内核态以及它们之间的切换"&gt;操作系统用户态和内核态以及它们之间的切换
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;用户态：调用系统 API（间接操作文件、网络等），运行普通应用程序，权限较低，不能直接访问硬件。&lt;/li&gt;
&lt;li&gt;内核态：操作系统内核运行状态，拥有最高权限，可以直接访问 CPU，内存，硬盘，网络设备等。&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="用户态和内核态切换"&gt;用户态和内核态切换
&lt;/h4&gt;&lt;p&gt;用户程序通过系统调用进入内核执行，再返回用户态的过程&lt;/p&gt;
&lt;pre class="mermaid" style="visibility:hidden"&gt;flowchart TD
 A["用户程序调用 read()"] --&gt; B[触发系统调用 syscall]
 B --&gt; C[CPU 切换到内核态 Kernel Mode]
 C --&gt; D[执行内核逻辑\n读取磁盘 / 网络 I/O]
 D --&gt; E[内核准备返回数据]
 E --&gt; F[CPU 切换回用户态 User Mode]
 F --&gt; G[用户程序获得返回结果]&lt;/pre&gt;&lt;h2 id="redis-1"&gt;Redis
&lt;/h2&gt;&lt;h3 id="redis-大-key-解决方案"&gt;Redis 大 Key 解决方案
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;定期使用 &lt;code&gt;redis-cli --bigkeys&lt;/code&gt; 命令进行扫描，快速定位可能的大 Key（注意：该命令为抽样统计，不保证全量精确）&lt;/li&gt;
&lt;li&gt;对于 Big List 一般采用拆分策略，比如按 1000 个元素一组进行分片存储；如果只关心最新数据，可以结合 &lt;code&gt;LTRIM&lt;/code&gt; 定期修剪，避免 List 无限增长导致阻塞操作（如 &lt;code&gt;LRANGE&lt;/code&gt; / &lt;code&gt;LLEN&lt;/code&gt; 变慢）&lt;/li&gt;
&lt;li&gt;对于 Big Hash，同样需要拆分，可以根据字段名做 hash 取模，将数据分散到多个小 Hash 中；并且在所有代码中，避免对大 Hash 使用 &lt;code&gt;HGETALL&lt;/code&gt;，应强制使用 &lt;code&gt;HSCAN&lt;/code&gt; 进行增量遍历，避免一次性全量拉取导致阻塞 Redis 单线程&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="scan-命令"&gt;&lt;code&gt;SCAN&lt;/code&gt; 命令
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;分批次增量遍历整个 Redis，每次只返回一小部分 key（避免 &lt;code&gt;KEYS&lt;/code&gt; 命令造成阻塞）&lt;/li&gt;
&lt;li&gt;基于游标（cursor）的遍历方式，非阻塞性操作，每次 &lt;code&gt;SCAN&lt;/code&gt; 只消耗很短时间，不影响主线程正常执行其他命令&lt;/li&gt;
&lt;li&gt;牺牲强一致性（可能出现重复或遗漏），换取高可用性与低阻塞性，适用于在线环境的渐进式遍历&lt;/li&gt;
&lt;li&gt;通常需要配合 &lt;code&gt;MATCH&lt;/code&gt;（模式匹配）和 &lt;code&gt;COUNT&lt;/code&gt;（控制每次扫描数量）使用，以提高扫描效率&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SCAN&lt;/code&gt; 不保证一次遍历完整数据集，必须循环直到 cursor 回到 0 才算完成一次完整遍历&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="redis-内存淘汰策略"&gt;Redis 内存淘汰策略
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;noeviction（默认）&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;不删除任何数据&lt;/li&gt;
&lt;li&gt;内存满后写入直接报错（OOM）&lt;/li&gt;
&lt;li&gt;适合：严格不能丢数据的场景&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;allkeys-lru&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;在所有 key 中，删除“最近最少使用”的 key&lt;/li&gt;
&lt;li&gt;最常用的缓存策略（推荐）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;volatile-lru&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;只在设置了 TTL 的 key 中做 LRU 淘汰&lt;/li&gt;
&lt;li&gt;永不过期的 key 不参与&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;allkeys-lfu&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;在所有 key 中删除“访问频率最低”的 key&lt;/li&gt;
&lt;li&gt;比 LRU 更智能（更适合热点数据）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;volatile-lfu&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;只在带 TTL 的 key 中按访问频率淘汰&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;allkeys-random&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;随机删除 key（不看冷热）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;volatile-random&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;在设置 TTL 的 key 中随机删除&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="redis-过期删除策略"&gt;Redis 过期删除策略
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;惰性删除（Lazy Deletion）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;访问 key 时才检查是否过期&lt;/li&gt;
&lt;li&gt;如果过期才删除&lt;/li&gt;
&lt;li&gt;优点：不耗 CPU&lt;/li&gt;
&lt;li&gt;缺点：过期 key 可能长期占内存&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;定期删除（Periodic Deletion）&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Redis 每隔一段时间随机抽查一批 key&lt;/li&gt;
&lt;li&gt;删除其中已过期的 key&lt;/li&gt;
&lt;li&gt;优点：平衡 CPU 和内存&lt;/li&gt;
&lt;li&gt;缺点：不是全量扫描&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;定期 + 惰性混合&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="redis-持久化策略"&gt;Redis 持久化策略
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;RDB（数据快照）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;优点：&lt;/strong&gt; 恢复速度快、对性能影响小、文件体积小。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺点：&lt;/strong&gt; 可能丢失最近一次快照之后的数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;AOF（追加日志）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;优点：&lt;/strong&gt; 数据安全性高，最多只丢最后一小段写入数据。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺点：&lt;/strong&gt; 文件体积大，恢复速度较慢。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;RDB + AOF（混合模式）&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;优点：&lt;/strong&gt; 兼顾恢复速度快和数据安全性高。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缺点：&lt;/strong&gt; 实现更复杂，占用资源略高。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="redis-集群模式"&gt;Redis 集群模式
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;主从复制：一主多从结构，主负责写、从负责读，用于数据备份和读扩展，但不支持自动分片，主节点宕机需要手动处理或配合其他机制。&lt;/li&gt;
&lt;li&gt;哨兵模式：在主从基础上增加监控和自动故障转移，主节点挂了可以自动选新主，但仍然是单主架构，容量扩展能力有限。&lt;/li&gt;
&lt;li&gt;Cluster 集群模式：官方分布式方案，通过分片（slot）把数据分散到多个主节点，实现水平扩展和自动故障转移，是生产环境大规模使用的方案，但配置和使用复杂度更高。&lt;/li&gt;
&lt;/ol&gt;</description></item></channel></rss>