# Spring Framework 深度解析:从使用到原理
# 1. Spring 是什么?一个现代化的"汽车工厂"比喻
想象一下你要造一辆汽车。传统方式是你自己:
- 去钢铁厂买钢材
- 找轮胎厂定制轮胎
- 联系发动机制造商
- 自己组装所有零件
而 Spring 框架就像一个现代化的汽车工厂:
- IOC 容器:是工厂的中央仓库和管理系统
- Bean:就是各种汽车零件
- 依赖注入:工厂自动把需要的零件送到装配线
- AOP:是工厂的质检和喷漆流水线
传统开发模式:
开发者 → 创建对象A → 创建对象B → 手动组装A和B → 使用
Spring 开发模式:
开发者 → 定义零件A、B → Spring工厂 → 自动组装 → 直接使用成品
2
3
4
5
# 2. Spring 框架组成:生态系统全景图
Spring 不是单一工具,而是一个完整的生态系统:
Spring 生态系统:
┌─────────────────────────────────────────────────────┐
│ Spring Framework Core │
│ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ IOC │ │ AOP │ │ Beans │ │
│ │ 容器管理 │ │ 切面编程 │ │ 对象管理 │ │
│ └──────────┘ └──────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────┤
│ Spring Web MVC │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │Dispatcher- │ │ Controller │ │ ViewResolver│ │
│ │ Servlet │ │ 控制器 │ │ 视图解析器 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
├─────────────────────────────────────────────────────┤
│ Spring Data │
│ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ JPA │ │ Redis│ │ Mongo │ │ JDBC │ │
│ └───────┘ └───────┘ └───────┘ └───────┘ │
├─────────────────────────────────────────────────────┤
│ Spring Security │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ 认证 │ │ 授权 │ │ 攻击防护 │ │
│ └───────┘ └───────┘ └───────┘ │
└─────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 3. Spring 简单入门:第一个 Spring 程序
让我们从一个最简单的例子开始,理解 Spring 的基本使用。
# 3.1 传统方式 vs Spring 方式
传统 Java 开发:
// 用户服务接口
public interface UserService {
String getUserName();
}
// 用户服务实现
public class UserServiceImpl implements UserService {
public String getUserName() {
return "张三";
}
}
// 测试类
public class TraditionalTest {
public static void main(String[] args) {
// 手动创建对象
UserService userService = new UserServiceImpl();
System.out.println(userService.getUserName());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Spring 方式:
<!-- applicationContext.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 声明 Bean -->
<bean id="userService" class="com.example.UserServiceImpl"/>
</beans>
2
3
4
5
6
7
8
9
10
// Spring 测试类
public class SpringTest {
public static void main(String[] args) {
// 加载 Spring 容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器获取对象
UserService userService = (UserService) context.getBean("userService");
System.out.println(userService.getUserName());
}
}
2
3
4
5
6
7
8
9
10
11
这个简单的例子展示了 Spring 的核心思想:对象不再由程序员创建,而是由 Spring 容器创建和管理。
# 4. Spring 核心之控制反转 (IOC)
# 4.1 什么是控制反转?
控制反转 (Inversion of Control) 是一种设计思想,将对象的创建、组装、管理权从程序员手中"反转"给容器。
餐馆点菜比喻:
- 传统方式:你亲自去菜市场买菜、找厨师、租厨房、自己做菜
- IOC 方式:去餐厅点菜,餐厅负责采购、烹饪、上菜
控制权转移过程:
┌─────────────────────────────────────────────────────────┐
│ 传统方式 (程序员控制) │
│ 开发者 → 创建对象 → 设置属性 → 调用方法 → 销毁对象 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ IOC方式 (容器控制) │
│ 开发者 → 定义Bean → Spring容器 → 创建Bean → 注入依赖 → 提供Bean │
└─────────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
# 4.2 依赖注入 (DI) 的三种方式
1. 构造器注入:
public class UserService {
private UserDao userDao;
// 构造器注入
public UserService(UserDao userDao) {
this.userDao = userDao;
}
}
2
3
4
5
6
7
8
XML 配置:
<bean id="userDao" class="com.example.UserDaoImpl"/>
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userDao"/>
</bean>
2
3
4
2. Setter 方法注入:
public class UserService {
private UserDao userDao;
// Setter 注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
2
3
4
5
6
7
8
<bean id="userService" class="com.example.UserService">
<property name="userDao" ref="userDao"/>
</bean>
2
3
3. 字段注入 (使用 @Autowired):
@Component
public class UserService {
@Autowired
private UserDao userDao;
}
2
3
4
5
# 4.3 依赖注入的直观展示
假设我们有三个类:Car、Engine、Wheel
注入前:
Car Engine Wheel
[空] [独立] [独立]
│ │ │
└──────────┴─────────┘
没有关联
构造器注入后:
┌─────────────┐
│ Spring │
│ 容器 │
└──────┬──────┘
│ 创建并注入
┌──────▼──────┐
Car Engine Wheel
[有Engine] [被注入] [被注入]
[有Wheel ]
│ │ │
└─────────┴──────────┘
完整汽车
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 5. Spring 核心之面向切面编程 (AOP)
# 5.1 AOP 核心概念
照片处理比喻:
- 原始照片:核心业务逻辑
- 滤镜:切面(日志、事务、安全等)
- 照片+滤镜:增强后的业务逻辑
AOP 处理流程:
┌─────────────────────────────────────────────────────────┐
│ 原始业务方法 (如保存用户) │
│ public void saveUser(User user) { │
│ 1. 核心逻辑:userDao.save(user); │
│ } │
└─────────────────────────────────────────────────────────┘
│
│ AOP 织入
▼
┌─────────────────────────────────────────────────────────┐
│ 增强后的业务方法 │
│ public void saveUser(User user) { │
│ 1. 开启事务 (@Before) │
│ 2. 记录日志 (@Before) │
│ 3. 核心逻辑:userDao.save(user); │
│ 4. 提交事务 (@After) │
│ 5. 记录结果 (@AfterReturning) │
│ (如果有异常:回滚事务 @AfterThrowing) │
│ } │
└─────────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 5.2 AOP 关键术语
- 连接点 (Joinpoint):程序执行过程中的某个点(如方法调用、异常抛出)
- 切点 (Pointcut):匹配连接点的表达式
- 通知 (Advice):在切点执行的动作
- 切面 (Aspect):通知 + 切点
- 织入 (Weaving):将切面应用到目标对象的过程
# 5.3 AOP 示例:日志切面
// 1. 定义切面
@Aspect
@Component
public class LoggingAspect {
// 2. 定义切点:匹配所有Service层方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceLayer() {}
// 3. 前置通知
@Before("serviceLayer()")
public void logBefore(JoinPoint joinPoint) {
System.out.println("方法开始: " + joinPoint.getSignature().getName());
System.out.println("参数: " + Arrays.toString(joinPoint.getArgs()));
}
// 4. 后置通知
@AfterReturning(pointcut = "serviceLayer()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("方法返回: " + result);
}
// 5. 异常通知
@AfterThrowing(pointcut = "serviceLayer()", throwing = "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error) {
System.out.println("方法异常: " + error.getMessage());
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 6. SpringMVC 请求流程和案例
# 6.1 SpringMVC 架构图
SpringMVC 请求处理流程图:
┌─────────────┐ HTTP请求 ┌──────────────┐
│ 客户端 │───────────────▶│Dispatcher- │
│ (浏览器/APP) │ │ Servlet │
└─────────────┘ └──────┬───────┘
│ 1. 接收请求
┌────────▼────────┐
│ HandlerMapping│
│ (处理器映射器) │
└────────┬────────┘
│ 2. 查找Handler
┌────────▼────────┐
│ HandlerAdapter │
│ (处理器适配器) │
└────────┬────────┘
│ 3. 执行Controller
┌────────▼────────┐
│ Controller │
│ (控制器) │
└────────┬────────┘
│ 4. 返回ModelAndView
┌────────▼────────┐
│ ViewResolver │
│ (视图解析器) │
└────────┬────────┘
│ 5. 解析视图
┌────────▼────────┐
│ View │
│ (视图) │
└────────┬────────┘
│ 6. 渲染响应
┌─────────────┐ HTTP响应 ┌──────▼───────┐
│ 客户端 │◀───────────────│Dispatcher- │
│ (浏览器/APP) │ │ Servlet │
└─────────────┘ └──────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 6.2 SpringMVC 简单示例
// 1. 控制器
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
// 2. 处理GET请求
@GetMapping("/list")
public String listUsers(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "user/list"; // 返回视图名称
}
// 3. 处理POST请求
@PostMapping("/add")
public String addUser(User user) {
userService.save(user);
return "redirect:/user/list"; // 重定向
}
// 4. 返回JSON数据
@GetMapping("/api/{id}")
@ResponseBody
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!-- 5. 视图模板 (user/list.html) -->
<!DOCTYPE html>
<html>
<head>
<title>用户列表</title>
</head>
<body>
<h1>用户列表</h1>
<table>
<tr>
<th>ID</th>
<th>姓名</th>
<th>邮箱</th>
</tr>
<!-- 使用Thymeleaf模板引擎 -->
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
<td th:text="${user.email}"></td>
</tr>
</table>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 7. Spring IOC 实现原理详解
# 7.1 IOC 体系结构设计
Spring IOC 容器是一个高度模块化的系统,主要分为以下几个核心组件:
IOC 容器体系结构:
┌─────────────────────────────────────────────────────────┐
│ BeanFactory (顶级接口) │
│ ┌─────────────────────────────────────────────┐ │
│ │ 提供基本功能: │ │
│ │ • getBean() │ │
│ │ • containsBean() │ │
│ │ • isSingleton() │ │
│ │ • getType() │ │
│ └─────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ ApplicationContext (扩展接口) │
│ ┌─────────────────────────────────────────────┐ │
│ │ 扩展功能: │ │
│ │ • 国际化支持 │ │
│ │ • 事件发布机制 │ │
│ │ • 资源加载 │ │
│ │ • 层级上下文 │ │
│ └─────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 具体实现类 │
│ ┌────────────┐ ┌────────────┐ ┌─────────────┐ │
│ │ClassPathXml│ │FileSystemXml│ │Annotation- │ │
│ │Application │ │Application │ │ConfigAppli- │ │
│ │ Context │ │ Context │ │ cationContext│ │
│ └────────────┘ └────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────┘
内部核心组件:
┌─────────────┐ 管理 ┌─────────────┐
│ Bean定义注册│◀─────────│ Bean定义读取│
│ (BeanDefinition) │ │ (BeanDefinitionReader)│
└──────┬──────┘ └─────────────┘
│注册
┌──────▼──────┐ ┌─────────────┐
│ Bean定义映射│ │ 依赖解决器 │
│ (BeanDefinitionMap)│ │ (DependencyResolver)│
└──────┬──────┘ └─────────────┘
│获取定义
┌──────▼──────┐ ┌─────────────┐
│ Bean工厂 │─────────▶│ Bean后处理器│
│ (BeanFactory)│ │ (BeanPostProcessor)│
└──────┬──────┘ └─────────────┘
│创建实例
┌──────▼──────┐
│ 单例池 │
│ (SingletonObjects)│
└─────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 7.2 IOC 初始化流程详解
IOC 容器的初始化是一个复杂的过程,主要包括以下几个阶段:
IOC 容器初始化流程:
阶段1:资源定位和加载
┌─────────┐ 读取 ┌─────────┐ 解析 ┌─────────┐
│ 资源 │───────────▶│ XML文档 │───────────▶│ Bean │
│ (XML文件)│ │ │ │ 定义信息 │
└─────────┘ └─────────┘ └─────────┘
阶段2:BeanDefinition 注册
┌─────────────────────────────────────────┐
│ BeanDefinitionRegistry │
│ ┌─────────────────────────────────┐ │
│ │ beanDefinitionMap: Map<String, │ │
│ │ BeanDefinition> │ │
│ │ ┌─────────────┬─────────────┐ │ │
│ │ │ beanName │ BeanDefinition│ │ │
│ │ ├─────────────┼─────────────┤ │ │
│ │ │ "userService"│ ... │ │ │
│ │ ├─────────────┼─────────────┤ │ │
│ │ │ "userDao" │ ... │ │ │
│ │ └─────────────┴─────────────┘ │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
阶段3:BeanFactory 后处理
┌─────────┐ 调用 ┌─────────┐ 修改 ┌─────────┐
│容器初始化│──────────▶│BeanFactory│─────────▶│ Bean │
│ │ │ 后处理器 │ │ Definition│
└─────────┘ └─────────┘ └─────────┘
例如:PropertyPlaceholderConfigurer
替换 ${jdbc.url} 为真实值
阶段4:Bean 实例化(懒加载或预实例化)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 7.3 Bean 生命周期详解
Bean 的生命周期是 Spring IOC 的核心,理解它对于掌握 Spring 至关重要:
Bean 生命周期完整流程:
┌─────────────────────────────────────────────────────────┐
│ 实例化前 (BeanPostProcessor) │
│ InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 实例化 (创建对象) │
│ 1. 构造器反射创建实例 │
│ 2. 如果是工厂方法,调用工厂方法创建 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 属性填充 (依赖注入) │
│ 1. @Autowired/@Resource/@Inject 注入 │
│ 2. XML中<property>配置注入 │
│ 3. 构造器注入 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Aware接口回调 (感知容器) │
│ 1. BeanNameAware.setBeanName() │
│ 2. BeanFactoryAware.setBeanFactory() │
│ 3. ApplicationContextAware.setApplicationContext() │
│ 4. ...其他Aware接口 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 初始化前 (BeanPostProcessor) │
│ BeanPostProcessor.postProcessBeforeInitialization() │
│ → @PostConstruct 方法执行 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 初始化 (InitializingBean) │
│ 1. InitializingBean.afterPropertiesSet() │
│ 2. init-method 指定的方法 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 初始化后 (BeanPostProcessor) │
│ BeanPostProcessor.postProcessAfterInitialization() │
│ → 可能的AOP代理创建 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Bean 就绪 │
│ 可被应用程序使用 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 使用阶段 │
│ getBean() → 业务方法调用 │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ 销毁阶段 │
│ 1. @PreDestroy 方法执行 │
│ 2. DisposableBean.destroy() │
│ 3. destroy-method 指定的方法 │
└─────────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# 7.4 循环依赖解决原理(三级缓存)
Spring 解决循环依赖的机制是其设计精妙之处,通过三级缓存实现:
循环依赖示例:
┌─────────────┐ 依赖 ┌─────────────┐
│ ServiceA │─────────────────▶│ ServiceB │
│ │◀─────────────────│ │
│ 需要ServiceB│ │ 需要ServiceA│
└─────────────┘ └─────────────┘
解决过程(三级缓存机制):
初始状态:所有缓存为空
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 一级缓存 │ │ 二级缓存 │ │ 三级缓存 │
│ (单例对象池) │ │ (早期暴露对象) │ │ (对象工厂) │
│ singletonObjects│ │ earlySingleton- │ │ singleton- │
│ │ │ Objects │ │ Factories │
│ 空 │ │ 空 │ │ 空 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
步骤1:创建 ServiceA
1. 开始创建 ServiceA,先放入三级缓存(对象工厂)
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ singletonObjects│ │ earlySingleton- │ │ singleton- │
│ │ │ Objects │ │ Factories │
│ │ │ │ │ ServiceA工厂 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
2. 填充 ServiceA 属性时发现需要 ServiceB
步骤2:创建 ServiceB
1. 开始创建 ServiceB,放入三级缓存
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ singletonObjects│ │ earlySingleton- │ │ singleton- │
│ │ │ Objects │ │ Factories │
│ │ │ │ │ ServiceA工厂 │
│ │ │ │ │ ServiceB工厂 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
2. 填充 ServiceB 属性时发现需要 ServiceA
3. 从三级缓存获取 ServiceA 的早期引用(通过工厂创建)
4. ServiceA 的早期引用放入二级缓存,从三级缓存移除
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ singletonObjects│ │ earlySingleton- │ │ singleton- │
│ │ │ Objects │ │ Factories │
│ │ │ ServiceA(早期) │ │ ServiceB工厂 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
步骤3:完成 ServiceB 创建
1. ServiceB 初始化完成,放入一级缓存
2. 从三级缓存移除 ServiceB 工厂
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ singletonObjects│ │ earlySingleton- │ │ singleton- │
│ ServiceB │ │ Objects │ │ Factories │
│ │ │ ServiceA(早期) │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
步骤4:完成 ServiceA 创建
1. ServiceA 获得完整的 ServiceB 引用
2. ServiceA 初始化完成,放入一级缓存
3. 从二级缓存移除 ServiceA 早期引用
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ singletonObjects│ │ earlySingleton- │ │ singleton- │
│ ServiceB │ │ Objects │ │ Factories │
│ ServiceA │ │ 空 │ │ 空 │
└─────────────────┘ └─────────────────┘ └─────────────────┘
最终:两个Bean都创建完成,循环依赖解决成功!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
核心源码解析:
// AbstractAutowireCapableBeanFactory.doCreateBean()
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) {
// 1. 实例化Bean
BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// 2. 将Bean工厂添加到三级缓存(解决循环依赖的关键)
boolean earlySingletonExposure = (mbd.isSingleton() &&
this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 添加到三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 3. 属性注入(可能触发依赖Bean的创建)
populateBean(beanName, mbd, instanceWrapper);
// 4. 初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}
// DefaultSingletonBeanRegistry 中的三级缓存
public class DefaultSingletonBeanRegistry {
// 一级缓存:完整的单例Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存:早期的单例对象(尚未完成属性填充)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
// 三级缓存:单例工厂(用于创建早期引用)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
// 获取Bean时的逻辑
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 1. 从一级缓存获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 2. 从二级缓存获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 3. 从三级缓存获取工厂,创建早期引用
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 放入二级缓存,从三级缓存移除
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
return singletonObject;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 8. Spring AOP 实现原理详解
# 8.1 AOP 切面的实现原理
AOP 的实现基于代理模式,Spring 在运行时动态创建代理对象来包装目标对象:
AOP 代理创建过程:
┌─────────────────────────────────────────────────────────┐
│ 目标对象 (Target) │
│ public class UserServiceImpl implements UserService { │
│ public void saveUser(User user) { │
│ // 核心业务逻辑 │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
│
│ Spring AOP 处理
▼
┌─────────────────────────────────────────────────────────┐
│ 代理对象 (Proxy) │
│ public class $Proxy implements UserService { │
│ private UserService target; │
│ private List<Advisor> advisors; │
│ │
│ public void saveUser(User user) { │
│ // 1. 执行前置通知 │
│ for(Advisor advisor : advisors) { │
│ advisor.before(); │
│ } │
│ │
│ // 2. 执行目标方法 │
│ target.saveUser(user); │
│ │
│ // 3. 执行后置通知 │
│ for(Advisor advisor : advisors) { │
│ advisor.after(); │
│ } │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 8.2 AOP 代理的创建时机和过程
AOP 代理创建流程:
阶段1:Bean初始化后处理
┌─────────┐ 调用 ┌──────────────┐ 检查 ┌─────────┐
│Bean初始 │──────────▶│BeanPostProcessor│────────▶│ 是否需要│
│化完成后 │ │ .post- │ │ AOP代理 │
│ │ │ ProcessAfter- │ │ │
│ │ │ Initialization │ │ │
└─────────┘ └──────────────┘ └─────────┘
│ │
│ 需要代理 │
▼ ▼
┌────────────────────┐
│ 创建AOP代理对象 │
│ 1. 获取所有Advisor │
│ 2. 选择合适的代理方式 │
│ - JDK动态代理 │
│ - CGLIB代理 │
│ 3. 创建代理对象 │
└────────────────────┘
│
▼
┌────────────────────┐
│ 返回代理对象给容器 │
│ (替换原始Bean) │
└────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 8.3 JDK 动态代理实现原理
JDK 动态代理基于接口,使用 java.lang.reflect.Proxy 类创建代理:
JDK 动态代理原理:
┌─────────────────────────────────────────────────────────┐
│ 原始接口和实现类 │
│ public interface UserService { │
│ void saveUser(User user); │
│ } │
│ │
│ public class UserServiceImpl implements UserService { │
│ public void saveUser(User user) { │
│ System.out.println("保存用户"); │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
│
│ Proxy.newProxyInstance()
▼
┌─────────────────────────────────────────────────────────┐
│ 生成的代理类结构 │
│ public class $Proxy0 extends Proxy │
│ implements UserService { │
│ │
│ // InvocationHandler 实例 │
│ private InvocationHandler h; │
│ │
│ // 接口方法 │
│ public void saveUser(User user) { │
│ // 调用 InvocationHandler.invoke() │
│ h.invoke(this, │
│ UserService.class.getMethod("saveUser"),│
│ new Object[]{user}); │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
│
│ 调用
▼
┌─────────────────────────────────────────────────────────┐
│ 自定义 InvocationHandler │
│ public class MyInvocationHandler │
│ implements InvocationHandler { │
│ │
│ private Object target; // 目标对象 │
│ private List<MethodInterceptor> interceptors; │
│ │
│ public Object invoke(Object proxy, Method method, │
│ Object[] args) throws Throwable {│
│ // 1. 执行前置拦截器 │
│ for(MethodInterceptor interceptor : interceptors) {│
│ interceptor.before(method, args); │
│ } │
│ │
│ // 2. 执行原始方法 │
│ Object result = method.invoke(target, args); │
│ │
│ // 3. 执行后置拦截器 │
│ for(MethodInterceptor interceptor : interceptors) {│
│ interceptor.after(method, args, result); │
│ } │
│ │
│ return result; │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
JDK 动态代理源码示例:
// Spring 中 JdkDynamicAopProxy 的核心代码
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler {
private final AdvisedSupport advised;
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
// 获取所有需要代理的接口
Class<?>[] proxiedInterfaces =
AopProxyUtils.completeProxiedInterfaces(this.advised);
// 使用 JDK Proxy 创建代理对象
return Proxy.newProxyInstance(classLoader,
proxiedInterfaces,
this);
}
// InvocationHandler 接口实现
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object retVal;
// 获取目标对象
TargetSource targetSource = this.advised.targetSource;
Object target = targetSource.getTarget();
try {
// 获取拦截器链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, target.getClass());
if (chain.isEmpty()) {
// 没有拦截器,直接调用目标方法
retVal = method.invoke(target, args);
} else {
// 创建方法调用器,执行拦截器链
invocation = new ReflectiveMethodInvocation(
proxy, target, method, args, target.getClass(), chain);
retVal = invocation.proceed();
}
return retVal;
} finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 8.4 CGLIB 代理实现原理
CGLIB(Code Generation Library)通过继承目标类并重写方法来实现代理:
CGLIB 代理原理:
┌─────────────────────────────────────────────────────────┐
│ 目标类 (没有接口) │
│ public class UserService { │
│ public void saveUser(User user) { │
│ System.out.println("保存用户"); │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
│
│ Enhancer.create()
▼
┌─────────────────────────────────────────────────────────┐
│ 生成的代理子类结构 │
│ public class UserService$$EnhancerByCGLIB$$abcd │
│ extends UserService { │
│ │
│ // 回调过滤器和方法拦截器 │
│ private MethodInterceptor interceptor; │
│ │
│ // 重写父类方法 │
│ public void saveUser(User user) { │
│ // 调用 MethodInterceptor.intercept() │
│ interceptor.intercept(this, │
│ super.getClass().getMethod("saveUser"),│
│ new Object[]{user}, │
│ super.methodProxy); │
│ } │
│ │
│ // 新增的CGLIB方法 │
│ public void saveUser$$cglib(User user) { │
│ super.saveUser(user); // 直接调用父类 │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
│
│ 调用
▼
┌─────────────────────────────────────────────────────────┐
│ MethodInterceptor 实现 │
│ public class MyMethodInterceptor │
│ implements MethodInterceptor { │
│ │
│ public Object intercept(Object obj, Method method,│
│ Object[] args, │
│ MethodProxy proxy) │
│ throws Throwable { │
│ // 1. 前置处理 │
│ System.out.println("方法开始: " + method.getName());│
│ │
│ // 2. 调用父类方法(原始方法) │
│ Object result = proxy.invokeSuper(obj, args);│
│ │
│ // 3. 后置处理 │
│ System.out.println("方法结束"); │
│ │
│ return result; │
│ } │
│ } │
└─────────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
CGLIB 代理的核心机制:方法索引和方法代理
CGLIB 方法调用优化机制:
原始类方法表:
┌──────────┬─────────────────────────┐
│ 方法索引 │ 方法签名 │
├──────────┼─────────────────────────┤
│ 0 │ saveUser(User) │
├──────────┼─────────────────────────┤
│ 1 │ deleteUser(Long) │
└──────────┴─────────────────────────┘
代理类方法表:
┌──────────┬─────────────────────────┐
│ 方法索引 │ 方法签名 │
├──────────┼─────────────────────────┤
│ 0 │ saveUser(User) │ → 重写的方法,调用拦截器
├──────────┼─────────────────────────┤
│ 1 │ deleteUser(Long) │ → 重写的方法,调用拦截器
├──────────┼─────────────────────────┤
│ 2 │ saveUser$$cglib(User) │ → 直接调用父类的方法
├──────────┼─────────────────────────┤
│ 3 │ deleteUser$$cglib(Long) │ → 直接调用父类的方法
└──────────┴─────────────────────────┘
FastClass 机制:
每个类都有一个 FastClass,通过方法索引直接调用方法,跳过反射:
正常反射调用:获取Method对象 → invoke()调用
FastClass调用:获取方法索引 → 直接调用(类似 switch-case)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CGLIB 源码示例:
// Spring 中 CglibAopProxy 的核心代码
class CglibAopProxy implements AopProxy {
private final AdvisedSupport advised;
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
// 创建 Enhancer
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
}
// 设置父类(目标类)
enhancer.setSuperclass(advised.getTargetClass());
enhancer.setInterfaces(advised.getProxiedInterfaces());
// 设置回调
Callback[] callbacks = getCallbacks(advised.getTargetClass());
enhancer.setCallbacks(callbacks);
// 创建代理对象
return enhancer.create();
}
private Callback[] getCallbacks(Class<?> rootClass) {
// 创建主要的 MethodInterceptor
Callback aopInterceptor = new DynamicAdvisedInterceptor(advised);
// 创建其他回调(用于性能优化)
Callback[] callbacks = new Callback[] {
aopInterceptor, // 0 - 主要的AOP拦截器
NoOp.INSTANCE, // 1 - 直接调用父类方法
};
return callbacks;
}
// 核心拦截器
private static class DynamicAdvisedInterceptor implements MethodInterceptor {
private final AdvisedSupport advised;
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
Object target = getTarget();
Class<?> targetClass = getTargetClass();
// 获取拦截器链
List<Object> chain = advised.getInterceptorsAndDynamicInterceptionAdvice(
method, targetClass);
if (chain.isEmpty()) {
// 没有拦截器,直接调用目标方法
return methodProxy.invoke(target, args);
} else {
// 创建CGLIB方法调用,执行拦截器链
CglibMethodInvocation invocation = new CglibMethodInvocation(
proxy, target, method, args, targetClass, chain, methodProxy);
return invocation.proceed();
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# 8.5 Spring 如何选择代理方式
Spring 根据以下规则决定使用 JDK 代理还是 CGLIB 代理:
代理方式选择逻辑:
开始选择代理方式
│
▼
┌─────────────────┐
│ 检查目标对象类型 │
└────────┬────────┘
│
▼
是否配置了优化选项?
├──是──▶ 使用CGLIB
│
▼
目标是否实现了接口?
├──否──▶ 使用CGLIB
│
▼
是否强制使用CGLIB?
├──是──▶ 使用CGLIB
│
▼
是否所有方法都是接口方法?
├──否──▶ 使用CGLIB
│
▼
┌───────────────┐
│ 使用JDK动态代理 │
└───────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 9. SpringMVC 实现原理详解
# 9.1 DispatcherServlet 的初始化过程
DispatcherServlet 是 SpringMVC 的核心,它的初始化是一个复杂的过程:
DispatcherServlet 初始化流程:
阶段1:Servlet 初始化 (init())
┌─────────────┐ 调用 ┌─────────────┐
│ Web容器 │──────────▶│Dispatcher- │
│ (Tomcat等) │ │ Servlet.init│
└─────────────┘ └──────┬──────┘
│
┌──────▼──────┐
│ 父类初始化 │
│ HttpServlet │
│ .init() │
└──────┬──────┘
│
┌──────▼──────┐
│ 初始化策略 │
│ initStrategies│
└──────┬──────┘
│
┌─────────────────┼─────────────────┐
│ │ │
┌───────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐
│ 初始化多部分解析│ │ 初始化本地化 │ │ 初始化主题解析│
│ initMultipart│ │ initLocale- │ │ initTheme- │
│ Resolver │ │ Resolver │ │ Resolver │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
┌───────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐
│ 初始化处理器映射│ │初始化处理器适配│ │初始化异常处理器│
│ initHandler- │ │ initHandler- │ │ initHandler- │
│ Mappings │ │ Adapters │ │ Exception- │
│ │ │ │ │ Resolvers │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
┌───────▼──────┐ ┌───────▼──────┐ ┌───────▼──────┐
│ 初始化视图解析器│ │初始化请求到视图名│ │初始化FlashMap│
│ initView- │ │ 转换器 │ │ 管理器 │
│ Resolvers │ │ initRequestTo│ │ initFlashMap│
│ │ │ ViewName- │ │ Manager │
│ │ │ Translator │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
关键组件初始化详解:
- HandlerMapping 初始化:
HandlerMapping 结构:
┌─────────────────────────────────────────────────────┐
│ HandlerMapping 接口 │
├─────────────────────────────────────────────────────┤
│ AbstractHandlerMapping │
├──────────────┬────────────────┬─────────────────────┤
│ RequestMapping-│ BeanNameUrl- │ SimpleUrlHandler- │
│ HandlerMapping│ HandlerMapping │ Mapping │
└──────────────┴────────────────┴─────────────────────┘
RequestMappingHandlerMapping 扫描过程:
┌─────────┐ 扫描 ┌─────────┐ 解析 ┌─────────┐
│ 容器中的 │─────────▶│ 所有Bean │─────────▶│ @Controller│
│ 所有Bean │ │ │ │ 和@RequestMapping│
└─────────┘ └─────────┘ └─────────┘
│ │ │
└──────────────────┼──────────────────┘
▼
┌─────────────────────┐
│ HandlerMethod映射表 │
├──────────┬──────────┤
│ URL │ Handler- │
│ 模式 │ Method │
├──────────┼──────────┤
│ /user/ │ User- │
│ list │ Controller│
│ │ .list() │
├──────────┼──────────┤
│ /user/ │ User- │
│ add │ Controller│
│ │ .add() │
└──────────┴──────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
- HandlerAdapter 初始化:
// HandlerAdapter 的主要实现
┌─────────────────────────────────────────────────────┐
│ HandlerAdapter 接口 │
├─────────────────────────────────────────────────────┤
│ AbstractHandlerMethodAdapter │
├─────────────────────────────────────────────────────┤
│ RequestMappingHandlerAdapter │
├─────────────────────────────────────────────────────┤
│ HttpRequestHandlerAdapter │
├─────────────────────────────────────────────────────┤
│ SimpleControllerHandlerAdapter │
└─────────────────────────────────────────────────────┘
// RequestMappingHandlerAdapter 初始化参数解析器和返回值处理器
protected void initControllerAdviceCache() {
// 1. 初始化 @ControllerAdvice
// 2. 初始化参数解析器(@RequestParam, @RequestBody, @PathVariable等)
// 3. 初始化返回值处理器(@ResponseBody, ModelAndView等)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 9.2 DispatcherServlet 处理请求的过程
当请求到达时,DispatcherServlet 按照以下流程处理:
请求处理完整流程:
┌─────────────────────────────────────────────────────────┐
│ 收到HTTP请求 │
└──────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ DispatcherServlet.service() │
│ 1. 判断请求方法类型 │
│ 2. 调用 doDispatch() │
└──────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────┐
│ doDispatch() │
└─────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 检查是否为文件上传请求 │
│ processedRequest = checkMultipart(request)│
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 查找对应的Handler │
│ mappedHandler = getHandler(processedRequest)│
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 获取对应的HandlerAdapter │
│ ha = getHandlerAdapter(mappedHandler.getHandler())│
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 执行拦截器的preHandle() │
│ mappedHandler.applyPreHandle()│
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 实际调用处理器方法 │
│ mv = ha.handle(processedRequest, response, mappedHandler.getHandler())│
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 设置默认视图名 │
│ applyDefaultViewName() │
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 执行拦截器的postHandle() │
│ mappedHandler.applyPostHandle()│
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 处理结果(渲染视图或写响应)│
│ processDispatchResult() │
└────────────┬───────────────┘
│
┌────────────▼──────────────┐
│ 执行拦截器的afterCompletion()│
│ triggerAfterCompletion() │
└─────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
详细步骤解析:
步骤1:获取 Handler(处理器)
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 遍历所有 HandlerMapping
for (HandlerMapping hm : this.handlerMappings) {
HandlerExecutionChain handler = hm.getHandler(request);
if (handler != null) {
return handler;
}
}
return null;
}
// HandlerExecutionChain 结构:
┌─────────────────────────────────────────────────────┐
│ HandlerExecutionChain │
├─────────────────────────────────────────────────────┤
│ handler: Object (实际的Controller或HandlerMethod) │
├─────────────────────────────────────────────────────┤
│ interceptors: List<HandlerInterceptor> │
│ ┌─────────────────────────────────────────────┐ │
│ │ interceptor1 (如:日志拦截器) │ │
│ │ interceptor2 (如:权限拦截器) │ │
│ │ interceptor3 (如:事务拦截器) │ │
│ └─────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
步骤2:HandlerAdapter 处理请求
// AbstractHandlerMethodAdapter.handle() 方法
public final ModelAndView handle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
// RequestMappingHandlerAdapter.handleInternal()
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response,
HandlerMethod handlerMethod) throws Exception {
// 1. 准备上下文
ServletWebRequest webRequest = new ServletWebRequest(request, response);
// 2. 执行处理器方法
ModelAndView mav = invokeHandlerMethod(request, response, handlerMethod);
return mav;
}
// invokeHandlerMethod() 详细过程:
1. 创建 ServletInvocableHandlerMethod
2. 设置参数解析器(HandlerMethodArgumentResolver)
3. 设置返回值处理器(HandlerMethodReturnValueHandler)
4. 执行方法调用
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
步骤3:参数解析过程
参数解析流程 (@GetMapping("/user/{id}") 为例):
请求URL:GET /user/123
│
▼
┌─────────────────────────────────────────────┐
│ 找到匹配的 HandlerMethod: │
│ UserController.getUser(@PathVariable Long id)│
└──────────────────────────┬──────────────────┘
│
┌─────────────▼─────────────┐
│ 遍历参数解析器 │
│ HandlerMethodArgumentResolver│
└─────────────┬─────────────┘
│
┌─────────────▼─────────────┐
│ 检查是否支持该参数类型 │
│ supportsParameter() │
└─────────────┬─────────────┘
│
┌─────────────▼─────────────┐
│ 解析参数值 │
│ resolveArgument() │
│ 1. 从路径获取"123" │
│ 2. 转换为Long类型 │
│ 3. 返回id=123 │
└───────────────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
步骤4:视图渲染过程
// DispatcherServlet.render() 方法
protected void render(ModelAndView mv, HttpServletRequest request,
HttpServletResponse response) throws Exception {
// 1. 获取视图对象
View view;
if (mv.isReference()) {
// 视图名,需要解析
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
} else {
// 已经是 View 对象
view = mv.getView();
}
// 2. 渲染视图
view.render(mv.getModelInternal(), request, response);
}
// 视图解析器链:
┌─────────────────────────────────────────────────────┐
│ ViewResolver 接口 │
├─────────────────────────────────────────────────────┤
│ AbstractCachingViewResolver │
├─────────────────────────────────────────────────────┤
│ UrlBasedViewResolver │
├───────┬─────────────┬─────────────┬─────────────────┤
│Internal│ XmlView │ Resource- │ Content- │
│Resource│ Resolver │ BundleView │ Negotiating │
│View- │ │ Resolver │ ViewResolver │
│Resolver│ │ │ │
└───────┴─────────────┴─────────────┴─────────────────┘
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
步骤5:异常处理机制
SpringMVC 异常处理流程:
┌─────────────┐ 发生异常 ┌─────────────┐
│ Controller │─────────────▶│Dispatcher- │
│ 执行方法 │ │ Servlet │
└─────────────┘ └──────┬──────┘
│
┌──────▼──────┐
│ 遍历异常处理器│
│ Handler- │
│ Exception- │
│ Resolver │
└──────┬──────┘
│
┌──────▼──────┐
│ 处理异常 │
│ 返回ModelAndView│
│ 或直接写响应 │
└──────┬──────┘
│
┌──────▼──────┐
│ 渲染错误页面│
│ 或返回JSON错误│
└──────────────┘
异常处理器类型:
1. @ExceptionHandler:控制器内部的异常处理
2. @ControllerAdvice:全局异常处理
3. HandlerExceptionResolver:自定义异常解析器
4. SimpleMappingExceptionResolver:简单映射异常处理器
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 10. 总结
Spring Framework 是一个强大而复杂的框架,但其核心设计思想可以概括为:
- IOC/DI:将对象的创建和管理权交给容器,实现松耦合
- AOP:通过代理模式实现横切关注点的分离
- MVC:基于前端控制器的Web开发模式
Spring 的设计哲学:
- 约定优于配置:提供合理的默认值
- 面向接口编程:提高代码的灵活性和可测试性
- 模板方法模式:消除重复代码(如JdbcTemplate)
- 开放封闭原则:通过扩展点支持定制
学习 Spring 的建议:
- 先学会使用,再研究原理
- 理解设计模式在 Spring 中的应用
- 阅读源码时,先看整体架构,再深入细节
- 动手实践,通过调试理解运行机制
Spring 的成功不仅在于其功能强大,更在于其优秀的设计思想和良好的扩展性。理解这些原理,不仅能帮助我们更好地使用 Spring,也能提升我们的软件设计能力。