From 2a2ba727fc9d28a88271ba8fba720214588c3180 Mon Sep 17 00:00:00 2001
From: "shuang.kou"
Date: Sat, 16 May 2020 15:37:00 +0800
Subject: [PATCH 1/7] =?UTF-8?q?Update=20Java=E9=9B=86=E5=90=88=E6=A1=86?=
=?UTF-8?q?=E6=9E=B6=E5=B8=B8=E8=A7=81=E9=9D=A2=E8=AF=95=E9=A2=98.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" | 2 ++
1 file changed, 2 insertions(+)
diff --git "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md" "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
index c664ca8f2ec..7c066c60d49 100644
--- "a/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
+++ "b/docs/java/collection/Java\351\233\206\345\220\210\346\241\206\346\236\266\345\270\270\350\247\201\351\235\242\350\257\225\351\242\230.md"
@@ -85,6 +85,8 @@ public interface RandomAccess {
**双向链表:** 包含两个指针,一个prev指向前一个节点,一个next指向后一个节点。
+> 另外推荐一篇把双向链表讲清楚的文章:[https://juejin.im/post/5b5d1a9af265da0f47352f14](https://juejin.im/post/5b5d1a9af265da0f47352f14)
+

**双向循环链表:** 最后一个节点的 next 指向head,而 head 的prev指向最后一个节点,构成一个环。
From c37d4f2c204e8b0695b7765299fa9a8eea47f972 Mon Sep 17 00:00:00 2001
From: "shuang.kou"
Date: Tue, 19 May 2020 16:16:47 +0800
Subject: [PATCH 2/7] =?UTF-8?q?Update=20Java=E5=9F=BA=E7=A1=80=E7=9F=A5?=
=?UTF-8?q?=E8=AF=86.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...72\347\241\200\347\237\245\350\257\206.md" | 81 +++++++++++--------
1 file changed, 46 insertions(+), 35 deletions(-)
diff --git "a/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md" "b/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
index 81baff9f25a..e902f9a9b59 100644
--- "a/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
+++ "b/docs/java/Java\345\237\272\347\241\200\347\237\245\350\257\206.md"
@@ -1,31 +1,29 @@
点击关注[公众号](#公众号)及时获取笔主最新更新文章,并可免费领取本文档配套的《Java 面试突击》以及 Java 工程师必备学习资源。
-
-
-- [1. Java基本功](#1-Java基本功)
- - [1.1 Java入门(基础概念与常识)](#1.1Java入门(基础概念与常识))
- - [1.2 Java语法](#1.2Java语法)
- - [1.3 Java流程控制](#1.3Java流程控制)
- - [1.4 数组](#1.4数组)
- - [1.5 方法(函数)](#1.5方法(函数))
-
-- [2. Java面向对象](#2-Java面向对象)
- - [2.1 类和对象](#2.1类和对象)
- - [2.2 面向对象三大特征](#2.2面向对象三大特征)
- - [2.3 修饰符](#2.3修饰符)
- - [2.4 接口](#2.4接口)
- - [2.5 类的扩展](#2.5类的扩展)
-- [3. Java核心技术](#3-关于-jvm-jdk-和-jre-最详细通俗的解答)
- - [3.1 集合](#3.1集合)
- - [3.2 异常](#3.2异常)
- - [3.3 多线程](#3.3多线程)
- - [3.4 文件与I\O流](#3.4文件与I\O流)
+
+- [1. Java 基本功](#1-Java基本功)
+ - [1.1 Java 入门(基础概念与常识)](#1.1Java入门(基础概念与常识))
+ - [1.2 Java 语法](#1.2Java语法)
+ - [1.3 Java 流程控制](#1.3Java流程控制)
+ - [1.4 数组](#1.4数组)
+ - [1.5 方法(函数)](#1.5方法(函数))
+- [2. Java 面向对象](#2-Java面向对象)
+ - [2.1 类和对象](#2.1类和对象)
+ - [2.2 面向对象三大特征](#2.2面向对象三大特征)
+ - [2.3 修饰符](#2.3修饰符)
+ - [2.4 接口](#2.4接口)
+ - [2.5 类的扩展](#2.5类的扩展)
+- [3. Java 核心技术](#3-关于-jvm-jdk-和-jre-最详细通俗的解答)
+ - [3.1 集合](#3.1集合)
+ - [3.2 异常](#3.2异常)
+ - [3.3 多线程](#3.3多线程)
+ - [3.4 文件与 I\O 流](#3.4文件与I\O流)
- [【附录】参考](#参考)
- [【附录】公众号](#公众号)
-
+## 1. Java 基本功
+
+### 1.1 Java 入门(基础概念与常识)
-## 1. Java基本功
-### 1.1 Java入门(基础概念与常识)
#### 1.1.1 Java 语言有哪些特点?
1. 简单易学;
@@ -112,7 +110,8 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有
所以,实际上 java 和 javax 没有区别。这都是一个名字。
-### 1.2 Java语法
+### 1.2 Java 语法
+
#### 1.2.1 字符型常量和字符串常量的区别?
1. 形式上: 字符常量是单引号引起的一个字符; 字符串常量是双引号引起的若干个字符
@@ -121,9 +120,13 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有
> java 编程思想第四版:2.2.2 节
> 
-### 1.3 Java流程控制
+
+### 1.3 Java 流程控制
+
### 1.4 数组
+
### 1.5 方法(函数)
+
#### 1.5.1 什么是方法的返回值?返回值在类的方法里的作用是什么?
方法的返回值是指我们获取到的某个方法体中的代码执行后产生的结果!(前提是该方法可能产生结果)。返回值的作用:接收出结果,使得它可以用于其他的操作!
@@ -162,12 +165,12 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有
| 区别点 | 重载方法 | 重写方法 |
| :--------- | :------- | :--------------------------------------------- |
-| 发生范围 | 同一个类 | 子类 中 |
+| 发生范围 | 同一个类 | 子类 中 |
| 参数列表 | 必须修改 | 一定不能修改 |
| 返回类型 | 可修改 | 一定不能修改 |
| 异常 | 可修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
| 访问修饰符 | 可修改 | 一定不能做更严格的限制(可以降低限制) |
-| 发生阶段 | 编译期 | 运行期 |
+| 发生阶段 | 编译期 | 运行期 |
#### 1.5.4 深拷贝 vs 浅拷贝
@@ -176,8 +179,10 @@ JRE 是 Java 运行时环境。它是运行已编译 Java 程序所需的所有

-## 2. Java面向对象
+## 2. Java 面向对象
+
### 2.1 类和对象
+
#### 2.1.1 面向对象和面向过程的区别
- **面向过程** :**面向过程性能比面向对象高。** 因为类调用时需要实例化,开销比较大,比较消耗资源,所以当性能是最重要的考量因素的时候,比如单片机、嵌入式开发、Linux/Unix 等一般采用面向过程开发。但是,**面向过程没有面向对象易维护、易复用、易扩展。**
@@ -210,7 +215,7 @@ new 运算符,new 创建对象实例(对象实例在堆内存中),对象
#### 2.1.6 一个类的构造方法的作用是什么? 若一个类没有声明构造方法,该程序能正确执行吗? 为什么?
-主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。如果我们自己添加了类的构造方法(无论是否有参),Java就不会再添加默认的无参数的构造方法了,这时候,就不能直接new一个对象而不传递参数了,所以我们一直在不知不觉地使用构造方法,这也是为什么我们在创建对象的时候后面要加一个括号(因为要调用无参的构造方法)。如果我们重载了有参的构造方法,记得都要把无参的构造方法也写出来(无论是否用到),因为这可以帮助我们在创建对象的时候少踩坑。
+主要作用是完成对类对象的初始化工作。可以执行。因为一个类即使没有声明构造方法也会有默认的不带参数的构造方法。如果我们自己添加了类的构造方法(无论是否有参),Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直在不知不觉地使用构造方法,这也是为什么我们在创建对象的时候后面要加一个括号(因为要调用无参的构造方法)。如果我们重载了有参的构造方法,记得都要把无参的构造方法也写出来(无论是否用到),因为这可以帮助我们在创建对象的时候少踩坑。
#### 2.1.7 构造方法有哪些特性?
@@ -229,6 +234,7 @@ new 运算符,new 创建对象实例(对象实例在堆内存中),对象
### 2.2 面向对象三大特征
#### 2.2.1 封装
+
封装是指把一个对象的状态信息(也就是属性)隐藏在对象内部,不允许外部对象直接访问对象的内部信息。但是可以提供一些可以被外界访问的方法来操作属性。就好像我们看不到挂在墙上的空调的内部的零件信息(也就是属性),但是可以通过遥控器(方法)来控制空调。如果属性不想被外界访问,我们大可不必提供方法给外界访问。但是如果一个类没有提供给外界访问的方法,那么这个类也没有什么意义了。就好像如果没有空调遥控器,那么我们就无法操控空凋制冷,空调本身就没有意义了(当然现在还有很多其他方法 ,这里只是为了举例子)。
```java
@@ -269,6 +275,7 @@ public class Student {
3. 子类可以用自己的方式实现父类的方法。(以后介绍)。
#### 2.2.3 多态
+
多态,顾名思义,表示一个对象具有多种的状态。具体表现为父类的引用指向子类的实例。
**多态的特点:**
@@ -281,6 +288,7 @@ public class Student {
- 如果子类重写了父类的方法,真正执行的是子类覆盖的方法,如果子类没有覆盖父类的方法,执行的是父类的方法。
### 2.3 修饰符
+
#### 2.3.1 在一个静态方法内调用一个非静态成员为什么是非法的?
由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。
@@ -325,6 +333,7 @@ final 关键字主要用在三个地方:变量、方法、类。
3. Jdk 9 在接口中引入了私有方法和私有静态方法。
### 2.5 类的扩展
+
#### 2.5.1 String StringBuffer 和 StringBuilder 的区别是什么? String 为什么是不可变的?
简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,`private final char value[]`,所以 String 对象是不可变的。
@@ -354,7 +363,6 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
}}
```
-
**线程安全性**
String 中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。
@@ -461,25 +469,26 @@ BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
String s = input.readLine();
```
-## 3. Java核心技术
+## 3. Java 核心技术
+
### 3.1 集合
+
#### 3.1.1 Collections 工具类和 Arrays 工具类常见方法总结
详见笔主的这篇文章: https://gitee.com/SnailClimb/JavaGuide/blob/master/docs/java/basic/Arrays,CollectionsCommonMethods.md
### 3.2 异常
+
#### 3.2.1 Java 异常类层次结构图

图片来自:https://simplesnippets.tech/exception-handling-in-java-part-1/
-

图片来自:https://chercher.tech/java-programming/exceptions-java
-
在 Java 中,所有的异常都有一个共同的祖先 java.lang 包中的 **Throwable 类**。Throwable: 有两个重要的子类:**Exception(异常)** 和 **Error(错误)** ,二者都是 Java 异常处理的重要子类,各自都包含大量子类。
**Error(错误):是程序无法处理的错误**,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。例如,Java 虚拟机运行错误(Virtual MachineError),当 JVM 不再有继续执行操作所需的内存资源时,将出现 OutOfMemoryError。这些异常发生时,Java 虚拟机(JVM)一般会选择线程终止。
@@ -532,6 +541,7 @@ public class Test {
如果调用 `f(2)`,返回值将是 0,因为 finally 语句的返回值覆盖了 try 语句块的返回值。
### 3.3 多线程
+
#### 3.3.1 简述线程、程序、进程的基本概念。以及他们之间关系是什么?
**线程**与进程相似,但线程是一个比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
@@ -561,7 +571,8 @@ Java 线程在运行的生命周期中的指定时刻只可能处于下面 6 种
当线程执行 `wait()`方法之后,线程进入 **WAITING(等待)**状态。进入等待状态的线程需要依靠其他线程的通知才能够返回到运行状态,而 **TIME_WAITING(超时等待)** 状态相当于在等待状态的基础上增加了超时限制,比如通过 `sleep(long millis)`方法或 `wait(long millis)`方法可以将 Java 线程置于 TIMED WAITING 状态。当超时时间到达后 Java 线程将会返回到 RUNNABLE 状态。当线程调用同步方法时,在没有获取到锁的情况下,线程将会进入到 **BLOCKED(阻塞)** 状态。线程在执行 Runnable 的`run()`方法之后将会进入到 **TERMINATED(终止)** 状态。
-### 3.3 文件与I\O流
+### 3.3 文件与 I\O 流
+
#### 3.3.1 Java 中 IO 流分为几种?
- 按照流的流向分,可以分为输入流和输出流;
@@ -607,4 +618,4 @@ Java Io 流共涉及 40 多个类,这些类看上去很杂乱,但实际上
**Java 工程师必备学习资源:** 一些 Java 工程师常用学习资源公众号后台回复关键字 **“1”** 即可免费无套路获取。
-
\ No newline at end of file
+
From 71ad98171d40b79236d30badb41e11c1ffcc8c27 Mon Sep 17 00:00:00 2001
From: "shuang.kou"
Date: Tue, 19 May 2020 16:18:18 +0800
Subject: [PATCH 3/7] Update Redis.md
---
docs/database/Redis/Redis.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/docs/database/Redis/Redis.md b/docs/database/Redis/Redis.md
index 7c00b5621bb..2ffee34fcaf 100644
--- a/docs/database/Redis/Redis.md
+++ b/docs/database/Redis/Redis.md
@@ -216,6 +216,8 @@ appendfsync no #让操作系统决定何时进行同步
为了兼顾数据和写入性能,用户可以考虑 appendfsync everysec 选项 ,让 Redis 每秒同步一次 AOF 文件,Redis 性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。当硬盘忙于执行写入操作的时候,Redis 还会优雅的放慢自己的速度以便适应硬盘的最大写入速度。
+[相关 Issue783:Redis的AOF 方式](https://github.com/Snailclimb/JavaGuide/issues/783)
+
**Redis 4.0 对于持久化机制的优化**
Redis 4.0 开始支持 RDB 和 AOF 的混合持久化(默认关闭,可以通过配置项 `aof-use-rdb-preamble` 开启)。
From 880226eb7f6388f95ff53b70c459eb388d617204 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Tue, 19 May 2020 16:34:31 +0800
Subject: [PATCH 4/7] Update reflection.md
---
docs/java/basic/reflection.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/docs/java/basic/reflection.md b/docs/java/basic/reflection.md
index 1dc3195dd6c..10e8736e63d 100644
--- a/docs/java/basic/reflection.md
+++ b/docs/java/basic/reflection.md
@@ -104,6 +104,13 @@ I love JavaGuide
value is JavaGuide
```
+**注意** : 有读者提到上面代码运行会抛出 `ClassNotFoundException` 异常,具体原因是你没有下面这段代码的包名替换成自己创建的 `TargetObject` 所在的包 。
+
+```java
+Class> tagetClass = Class.forName("cn.javaguide.TargetObject");
+```
+
+
### 静态编译和动态编译
- **静态编译:** 在编译时确定类型,绑定对象
From 365afd69743b470fc5b3e86359a75a7bfdfb8ce2 Mon Sep 17 00:00:00 2001
From: SnailClimb
Date: Tue, 19 May 2020 16:35:29 +0800
Subject: [PATCH 5/7] Update reflection.md
---
docs/java/basic/reflection.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/java/basic/reflection.md b/docs/java/basic/reflection.md
index 10e8736e63d..b243bef2bf7 100644
--- a/docs/java/basic/reflection.md
+++ b/docs/java/basic/reflection.md
@@ -104,7 +104,7 @@ I love JavaGuide
value is JavaGuide
```
-**注意** : 有读者提到上面代码运行会抛出 `ClassNotFoundException` 异常,具体原因是你没有下面这段代码的包名替换成自己创建的 `TargetObject` 所在的包 。
+**注意** : 有读者提到上面代码运行会抛出 `ClassNotFoundException` 异常,具体原因是你没有下面把这段代码的包名替换成自己创建的 `TargetObject` 所在的包 。
```java
Class> tagetClass = Class.forName("cn.javaguide.TargetObject");
From 5168cb87958902833564f57840d01984bce27895 Mon Sep 17 00:00:00 2001
From: "shuang.kou"
Date: Wed, 20 May 2020 15:21:29 +0800
Subject: [PATCH 6/7] =?UTF-8?q?Update=20=E9=98=BF=E9=87=8C=E5=B7=B4?=
=?UTF-8?q?=E5=B7=B4=E5=BC=80=E5=8F=91=E6=89=8B=E5=86=8C=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E5=BA=93=E9=83=A8=E5=88=86=E7=9A=84=E4=B8=80=E4=BA=9B=E6=9C=80?=
=?UTF-8?q?=E4=BD=B3=E5=AE=9E=E8=B7=B5.md?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
...\272\233\346\234\200\344\275\263\345\256\236\350\267\265.md" | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git "a/docs/database/\351\230\277\351\207\214\345\267\264\345\267\264\345\274\200\345\217\221\346\211\213\345\206\214\346\225\260\346\215\256\345\272\223\351\203\250\345\210\206\347\232\204\344\270\200\344\272\233\346\234\200\344\275\263\345\256\236\350\267\265.md" "b/docs/database/\351\230\277\351\207\214\345\267\264\345\267\264\345\274\200\345\217\221\346\211\213\345\206\214\346\225\260\346\215\256\345\272\223\351\203\250\345\210\206\347\232\204\344\270\200\344\272\233\346\234\200\344\275\263\345\256\236\350\267\265.md"
index 7eb84001c00..abd9331d6f7 100644
--- "a/docs/database/\351\230\277\351\207\214\345\267\264\345\267\264\345\274\200\345\217\221\346\211\213\345\206\214\346\225\260\346\215\256\345\272\223\351\203\250\345\210\206\347\232\204\344\270\200\344\272\233\346\234\200\344\275\263\345\256\236\350\267\265.md"
+++ "b/docs/database/\351\230\277\351\207\214\345\267\264\345\267\264\345\274\200\345\217\221\346\211\213\345\206\214\346\225\260\346\215\256\345\272\223\351\203\250\345\210\206\347\232\204\344\270\200\344\272\233\346\234\200\344\275\263\345\256\236\350\267\265.md"
@@ -21,7 +21,7 @@
> 1. **增加了复杂性:** a.每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便;b.外键的主从关系是定的,假如那天需求有变化,数据库中的这个字段根本不需要和其他表有关联的话就会增加很多麻烦。
> 2. **增加了额外工作**: 数据库需要增加维护外键的工作,比如当我们做一些涉及外键字段的增,删,更新操作之后,需要触发相关操作去检查,保证数据的的一致性和正确性,这样会不得不消耗资源;(个人觉得这个不是不用外键的原因,因为即使你不使用外键,你在应用层面也还是要保证的。所以,我觉得这个影响可以忽略不计。)
> 3. 外键还会因为需要请求对其他表内部加锁而容易出现死锁情况;
-> 4. **对分不分表不友好** :因为分库分表下外键是无法生效的。
+> 4. **对分库分表不友好** :因为分库分表下外键是无法生效的。
> 5. ......
我个人觉得上面这种回答不是特别的全面,只是说了外键存在的一个常见的问题。实际上,我们知道外键也是有很多好处的,比如:
From 83982860ec7c94fae23469074ea327ff4652feda Mon Sep 17 00:00:00 2001
From: "shuang.kou"
Date: Wed, 20 May 2020 15:22:04 +0800
Subject: [PATCH 7/7] Update README.md
---
README.md | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 2f5de457a2e..36997655cbc 100644
--- a/README.md
+++ b/README.md
@@ -54,7 +54,7 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git
- [系统设计](#系统设计)
- [必知](#必知)
- [常用框架](#常用框架)
- - [Spring](#spring)
+ - [Spring](#springspringboot)
- [SpringBoot](#springboot)
- [MyBatis](#mybatis)
- [认证授权(JWT、SSO)](#认证授权)
@@ -228,9 +228,10 @@ Github用户如果访问速度缓慢的话,可以转移到[码云](https://git
3. **[SpringBoot 指南/常见面试题总结](https://github.com/Snailclimb/springboot-guide)**
3. **[Spring/Spring常用注解总结!安排!](./docs/system-design/framework/spring/spring-annotations.md)**
4. **[Spring事务总结](docs/system-design/framework/spring/spring-transaction.md)**
-5. [Spring中 Bean 的作用域与生命周期](docs/system-design/framework/spring/SpringBean.md)
-6. [SpringMVC 工作原理详解](docs/system-design/framework/spring/SpringMVC-Principle.md)
-7. [Spring中都用到了那些设计模式?](docs/system-design/framework/spring/Spring-Design-Patterns.md)
+5. [Spring IoC 和 AOP详解](https://mp.weixin.qq.com/s?__biz=Mzg2OTA0Njk0OA==&mid=2247486938&idx=1&sn=c99ef0233f39a5ffc1b98c81e02dfcd4&chksm=cea24211f9d5cb07fa901183ba4d96187820713a72387788408040822ffb2ed575d28e953ce7&token=1666190828&lang=zh_CN#rd)
+6. [Spring中 Bean 的作用域与生命周期](docs/system-design/framework/spring/SpringBean.md)
+7. [SpringMVC 工作原理详解](docs/system-design/framework/spring/SpringMVC-Principle.md)
+8. [Spring中都用到了那些设计模式?](docs/system-design/framework/spring/Spring-Design-Patterns.md)
#### MyBatis