Java 中的 IoC、AOP、MVC
这三者是 Java 企业级开发中的核心设计思想和架构模式,经常在 Spring 框架中一起使用。
一、IoC — 控制反转
是什么?
控制反转(Inversion of Control)是一种设计原则:将对象的创建和依赖关系的管理交给容器,而不是由对象自己控制。
传统方式 vs IoC 方式
public class UserService {
private UserDao userDao = new UserDao();
private EmailUtil emailUtil = new EmailUtil();
}
public class UserService {
@Autowired
private UserDao userDao;
@Autowired
private EmailUtil emailUtil;
}
核心作用
| 作用 | 说明 |
|---|
| 解耦 | 类之间不再硬编码依赖,降低耦合度 |
| 可测试性 | 方便用 Mock 对象替换真实依赖进行单元测试 |
| 统一管理 | 对象的创建、销毁、作用域由容器统一管理 |
| 配置灵活 | 通过配置切换实现(如切换数据库实现类) |
相关概念
- DI(依赖注入):IoC 的实现方式,通过构造器、Setter 或注解注入依赖
- 容器:Spring Container 负责管理 Bean 的生命周期
二、AOP — 面向切面编程
是什么?
面向切面编程(Aspect-Oriented Programming)是一种编程范式,将横切关注点(如日志、事务、权限)从业务逻辑中抽离出来,统一处理。
典型场景
public void transferMoney() {
logger.info("开始转账");
startTransaction();
accountService.transfer();
commitTransaction();
logger.info("转账结束");
}
@Transactional
public void transferMoney() {
accountService.transfer();
}
核心概念
| 术语 | 说明 |
|---|
| 切面(Aspect) | 横切关注点的模块化,如 LogAspect、TransactionAspect |
| 通知(Advice) | 具体要执行的增强代码(前置、后置、环绕、异常、最终) |
| 切入点(Pointcut) | 匹配连接点的表达式,如 execution(* com..*.*(..)) |
| 连接点(JoinPoint) | 程序执行过程中的一个点,如方法调用、异常抛出 |
| 织入(Weaving) | 将切面应用到目标对象的过程 |
常见应用场景
| 场景 | 作用 |
|---|
| 日志记录 | 统一记录方法入参、返回值、执行时间 |
| 事务管理 | 声明式事务 @Transactional |
| 权限校验 | @PreAuthorize 统一鉴权 |
| 性能监控 | 统计方法执行耗时 |
| 缓存管理 | @Cacheable 统一缓存处理 |
| 异常处理 | 统一捕获并封装异常 |
三、MVC — 模型-视图-控制器
是什么?
MVC 是一种架构模式,将应用程序分成三个核心组件,实现关注点分离。
三层结构
用户请求
↓
┌─────────────────────────────────────────┐
│ Controller(控制器) │
│ - 接收请求,解析参数 │
│ - 调用业务逻辑 │
│ - 返回视图或数据 │
└─────────────────────────────────────────┘
↓ 调用
┌─────────────────────────────────────────┐
│ Model(模型) │
│ - 业务逻辑(Service) │
│ - 数据访问(DAO/Repository) │
│ - 实体类(Entity) │
└─────────────────────────────────────────┘
↓ 返回数据
┌─────────────────────────────────────────┐
│ View(视图) │
│ - JSP / Thymeleaf / Vue / React │
│ - 展示数据给用户 │
└─────────────────────────────────────────┘
Spring MVC 示例
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public Result getUser(@PathVariable Long id) {
User user = userService.getById(id);
return Result.success(user);
}
}
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getById(Long id) {
return userMapper.selectById(id);
}
}
MVC 核心作用
| 组件 | 职责 | 作用 |
|---|
| Controller | 请求分发、参数绑定、视图跳转 | 接收用户输入,协调 Model 和 View |
| Model | 业务逻辑、数据访问、状态维护 | 封装数据和业务规则 |
| View | 数据展示、用户交互 | 将数据显示给用户 |
优点
- 关注点分离:修改 UI 不影响业务逻辑
- 可维护性高:各层独立开发、测试
- 复用性好:同一 Model 可对应多个 View
三者的关系(结合 Spring)
┌─────────────────────────────────────────────────────┐
│ Spring Framework │
├─────────────────────────────────────────────────────┤
│ IoC 容器 ──────→ 管理所有 Bean 的生命周期和依赖 │
│ ↓ │
│ AOP 切面 ──────→ 为 Bean 添加横切能力(事务/日志) │
│ ↓ │
│ Spring MVC ─────→ Web 层的请求响应处理 │
└─────────────────────────────────────────────────────┘
典型调用流程
1. 用户发起请求 → Spring MVC 的 DispatcherServlet 接收
2. Controller 处理请求(Controller 由 IoC 容器管理)
3. 调用 Service 层业务逻辑(AOP 事务切面自动开启/提交事务)
4. Service 调用 DAO 层访问数据库
5. 返回数据 → Spring MVC 返回 JSON 或 视图给前端
对比总结
| 概念 | 类型 | 核心问题 | 典型实现 |
|---|
| IoC | 设计原则 | "对象谁来创建和管理?" | Spring Container |
| AOP | 编程范式 | "横切逻辑如何复用?" | Spring AOP、AspectJ |
| MVC | 架构模式 | "Web 层代码如何分层?" | Spring MVC、Struts |
一句话总结
- IoC:把对象创建权交给容器,解耦依赖
- AOP:把通用功能抽成切面,消除重复代码
- MVC:把 Web 层分成三层,分离关注点