目录
[🎯首先学习Spring IOC/DI](#🎯首先学习Spring IOC/DI)
[1、Spring IOC/DI整体框架](#1、Spring IOC/DI整体框架)
[1.1 核心思想:](#1.1 核心思想:)
[1.2 两个关键字:](#1.2 两个关键字:)
[1.3 对象之间的依赖关系](#1.3 对象之间的依赖关系)
2、真实案例(对比传统java和Spring(IOC和DI)):
[2.1 ❌ 场景一:传统java没有Spring------"自己动手,丰衣足食"](#2.1 ❌ 场景一:传统java没有Spring——“自己动手,丰衣足食”)
[2.2 ✅ 场景二:使用 Spring(IOC + DI)------ "点菜式开发"](#2.2 ✅ 场景二:使用 Spring(IOC + DI)—— “点菜式开发”)
[2.2.2 、启动Spring容器(配置扫描)](#2.2.2 、启动Spring容器(配置扫描))
[4、 常见问题:](#4、 常见问题:)
[🎯若依中Spring IOC、DI注解](#🎯若依中Spring IOC、DI注解)
3、IOC:实现Service(关键:使用@Service)
[5、Spring Boot启动类(环境初始化)](#5、Spring Boot启动类(环境初始化))
[🎯Spring MVC](#🎯Spring MVC)
[1、🌟 Spring MVC 工作流程](#1、🌟 Spring MVC 工作流程)
[📌 1. @Controller ------ "我是一个网页控制器"](#📌 1. @Controller —— “我是一个网页控制器”)
[📌 2. @RestController ------ "我是一个 API 控制器"](#📌 2. @RestController —— “我是一个 API 控制器”)
[📌 3. @RequestMapping ------ "这个方法处理哪个路径?"](#📌 3. @RequestMapping —— “这个方法处理哪个路径?”)
[📌 4. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping ------ "我只处理哪种请求?"](#📌 4. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping —— “我只处理哪种请求?”)
[📌 5. @RequestBody ------ "请求体里的 JSON 怎么读?"](#📌 5. @RequestBody —— “请求体里的 JSON 怎么读?”)
[📌6. @ResponseBody ------ "返回值怎么变成 JSON?"](#📌6. @ResponseBody —— “返回值怎么变成 JSON?”)
[🎯若依中Spring MVC注解](#🎯若依中Spring MVC注解)
[📌示例:实现一个 "用户管理"接口,功能包括:](#📌示例:实现一个 “用户管理”接口,功能包括:)
[1️⃣ 第一步:定义统一返回结果类](#1️⃣ 第一步:定义统一返回结果类)
[2️⃣ 第二步:定义实体类(用户)](#2️⃣ 第二步:定义实体类(用户))
[3️⃣ 第三步:定义 Service 接口与实现(供 Controller 调用)](#3️⃣ 第三步:定义 Service 接口与实现(供 Controller 调用))
[4️⃣ 第四步:定义 Controller(核心!Spring MVC 注解集中地)](#4️⃣ 第四步:定义 Controller(核心!Spring MVC 注解集中地))
[5️⃣ 第五步:Spring Boot 启动类(环境初始化)](#5️⃣ 第五步:Spring Boot 启动类(环境初始化))
🎯首先学习Spring IOC/DI
1、Spring IOC/DI整体框架

1.1 核心思想:
- 所有的对象都不用new,而是交给Spring容器创建和管理(IOC)
- 对象之间的依赖关系,由Spring自动"塞进去"(DI)
1.2 两个关键字:
- IOC(控制反转): 对像的创建权从人-->交给Spring
- DI(依赖注入): 对象的依赖关系有Spring自动填充
1.3 对象之间的依赖关系
- 对象之间的依赖关系=一个对象需要另一个对象才能工作(就像你吃饭需要筷子,你依赖筷子)
- 一个程序中的类需要别的类才能完成任务,这就是 "依赖"
在代码中:
java
@Service
public class OrderService{
//这个OrderService需要UserService来查询永辉想你想
@Autowired//自动注入UserService类
private OrderService orderService;
public void createOrder(){
userService.getUserInfo();//直接使用UserService中的方法
}
}

2、真实案例(对比传统java和Spring(IOC和DI)):
用户下单时需要保存用户信息 ------------ 搞懂IOC/DI
2.1 ❌ 场景一:传统java没有Spring------"自己动手,丰衣足食"
2.1.1、定义一个服务类
java
//定义一个服务类
//用户服务
public class UserService{
public void saveUser(){
System.out.println("保存用户到数据库");
}
}
//订单服务(强依赖UserService)
public class OrderService{
//问题1:硬编码new,耦合死死的
private UserService userService=new UserService();
public void createOrder(){
System.out.println("创建订单.....");
userService.saveUser();//调用
}
}
2.1.2、使用方法
java
public class Main{
public static void main(String[] args){
//问题2:你自己控制一切,无法灵活替换实现
OrderService orderService=new Override();
orderService.createOrder();
}
}
| 问题 | 后果 |
|---|---|
| new UserService()写死 | 换实现?改代码! |
| 对象的声明周期自己管 | 内存、单例、线程安全全靠手写 |
| 测试困难 | 想mock UserService? 几乎不可能 |
| [传统方式的痛点] |
2.2 ✅场景二:使用 Spring(IOC + DI)------ "点菜式开发"
2.2.1、定义服务类(加注解)
java
//告诉Spring:请管理我
@Service
public class UserService{
public void saveUser(){
System.out.println("保存用户到数据库(由Spring管理");
}
}
//告诉Spring:我也被管理,并且我需要UserService
@Service
public class OrderService{}
//不New 只声明"我需要他
@Autowired
private UserService userService;
public void createOrder(){
System.out.println("创建订单(Spring注入依赖");
userService.saveUser();
}
- @Service是告诉Spring:"这个类很重要,请帮我管理"
- @Autowired是说:"我需要某个对象,请Sping 自动给我塞进来"
- 但接下来的问题是:Spring怎么知道去哪里找到这些类?怎么启动Spring容器------这时候我们就需要写一个"启动开关(SpringConfig类)"
- SpringConfig作用:请从这个包开始扫描所有带@Component、@Service、@Controller的类,把他们都编程Bean放进容器里,然后开启服务!
2.2.2 、启动Spring容器(配置扫描)
java
//配置类:告诉Spring从那个包开始找@Compent类
//表示这是一个配置类,相当于以前的xml文件------------>作用:告诉Spring这是你的说明书,请按这个来设置容器
@Configuration
//告诉Sring,请从这个包目录开始,自动扫描所有带@Component、@Service、@Controller、@Repository注解的类,把这些类都注册到Spring容器里面
//注册之后Spring就会自动发现这些类,并创建类对象放进容器里
@ComponentScan(basePackages="com.example.service")
public class SpringConfig{
//空配置类即可
}
-
流程梳理:
启动程序时,Spring 会:
- 读取 SpringConfig
- 开始扫描 com.example.service 包下的类
- 发现 UserService 和 OrderService,把它们创建成对象,放进容器
- 当 OrderService 里有 @Autowired private UserService userService; 时 → Spring 自动把 UserService 对象注入进来
- 程序就可以正常运行了
- 补充: @Configuration + @ComponentScan 是告诉 Spring:"请从指定包里找出所有带注解的类,把它们变成对象放进来管理。
-
为什么需要启动类:
@Configuration + @ComponentScan是"配置"阶段,告诉 Spring 去哪找类------------但这还不够, 我们需要一个"主程序 "来启动真正的Spring容器,然后从容器里拿对象使用。
--因为java程序不会自己运行,必须有人启动他
--Spring容器不是魔法------它是个普通的java对象,需要人主动创建它,它才会开始工作(IOC /DI)
--本质:
①java是静态语言,代码不会自己跑起来
②Spring容器只是一个库(library),它不会在你编译或写代码时自动激活
③必须由你的程序主动创建容器实例,它才会开始扫描、注册、注入
2.2.3、使用方法(从容器中拿对象)------启动类
java
public class Main{
public static void main(String[] args){
//启动Spring容器(IOC容器)
//AnnotationConfigApplicationContext:这是Spring容器提供的一个"启动器",专门用来加载基于Java注解的配置
//SpringConfig.class是请按照配置类来启动容器
//即:请根据SpringConfig配置,启动Spring容器,开始扫描包,创建Bean、管理依赖
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
//从容器中获取对象(不是new)
//context.getBean():是Spring提供的方法,用来从容器中"拿"对象
//OrderService.class:你要的是哪一个类的对象
//返回的是一个OrderService实例,这个实例已经被Spring创建好了,而且里面的userService也已经自动注入
OrderService orderService=context.getBean(OrderService.class);
//动用(userService已自动注入
//最后调用方法执行逻辑
//因为 userService 已经被 @Autowired 自动注入了,所以可以正常调用。
orderService.createOrder();
}
}
| 优势 | 说明 |
| 解耦 | OrderService不需要知道UserService怎么创建 |
| 灵活替换 | 只要实现相同的接口,换实现不用改一行代码 |
| 单例自动管理 | 默认每个Bean是单例,Spring保证线程安全 |
| 易于测试 | 单元测试时可轻松注入Mock对象 |
|---|---|
| [Spring方式的优点] |
3、总结对比
| 维度 | 传统方式 | Spring(IOC+DI) |
| 谁创建对象? | 你自己new | Spring 容器创建 |
| 谁管理对象? | 你自己管生命周期 | Spring统一管理 |
| 依赖怎么来? | 手动new或者传参 | @Autowired自动注入 |
| 代码耦合度 | 高(紧耦合) | 低(松耦合) |
| 可维护性 | 差(改一改动全身) | 好(插拔式开发) |
|---|
- IOC是思想,DI是实现IOC的手段
4、 常见问题:
?Q:@Autowired是怎么知道注入那个对象的?
- 默认类型(TYPE)匹配
- 如果有多个同类型Bean,可以使用@Aualifier("beanName)指定名字
**?**Q:Spring容器什么时候创建这些对象
- 默认是singleton(单例),容器启动时就创建好
- 也可以设置为@Scope("prototype"),每次getBean都新建
**?**Q:一定药用注解吗,能不能用XML?
- 可****以!早期用 XML 配置,现在主流是 注解 + Java Config
- @Component + @Autowired 是最现代、最简洁的方式
🎯若依中Spring IOC、DI注解
-
以实现**"岗位管理** "功能为例
包含:
-
SysPostController(控制器)
-
ISysPostService(接口)+SyePostServiceImpl(实现)
-
使用@Autowired注入依赖
1、定义实体类

2、定义Service接口

3、IOC:实现Service(关键:使用@Service)

4、**DI:**定义Controller,注入Service

5、Spring Boot启动类****(环境初始化)

6、整个流程:
┌──────────────────────┐ │ 启动 Spring │ │ (new AnnotationConfig│ │ ApplicationContext) │ └─────────┬────────────┘ ▼ ┌──────────────────────┐ │ 扫描指定包路径 │ │ (如:com.example) │ └─────────┬────────────┘ ▼ ┌─────────────────────────────┐ │ 发现 @Service 标注的类 │ │ → SysPostServiceImpl │ └─────────┬───────────────────┘ ▼ ┌──────────────────────┐ │ 创建 Bean 实例 │ │ 并注册到 Spring 容器 │ └─────────┬────────────┘ ▼ ┌─────────────────────────────┐ │ 发现 @RestController 标注的类│ │ → SysPostController │ └─────────┬───────────────────┘ ▼ ┌──────────────────────┐ │ 创建 SysPostController│ │ 的 Bean 实例 │ └─────────┬────────────┘ ▼ ┌───────────────────────────────────────┐ │ 执行依赖注入(DI) │ │ → 在 SysPostController 中 │ │ @Autowired │ │ private SysPostServiceImpl userService;│ │ → Spring 自动将容器中的 │ │ SysPostServiceImpl Bean 注入进来 │ └─────────┬─────────────────────────────┘ ▼ ┌──────────────────────┐ │ 等待 HTTP 请求到来 │ └─────────┬────────────┘ ▼ ┌──────────────────────┐ │ 调用 Controller 方法 │ │ → 方法内部使用 │ │ userService.doXXX() │ │ → 依赖正常工作 ✅ │ └──────────────────────┘补充:
- 整个过程由Spring容器触发
- @Service和@RestController都是@Component的派生注解,会被@CoponentScan自动发现
- @Autowired一来注入发生在Bean创建之后、请求处理之前
- 最终调用链:HTTP请求-->Controller-->Service,依赖已就绪
7、关键总结(Ruoyi中IOC/DI的使用模式)
| 步骤 | 注解 | 作用 |
|---|---|---|
| 1. 定义实现类 | @Service |
将自定义类型注册为 Spring Bean |
| 2. 声明依赖 | @Autowired |
自动从容器中查找匹配的 Bean 并注入 |
| 3. 启动容器 | @SpringBootApplication |
自动开启组件扫描 + IOC 容器初始化 |
🎯Spring MVC
1、🌟 Spring MVC 工作流程

- Spring MVC=前端发起请求-->Spring找到对于方法-->处理数据-->返回响应
2、注解
📌 1. @Controller ------ "我是一个网页控制器"
- 作用:告诉 Spring:"这个类是用来处理前端请求的"
- 特点:
- 默认返回的是 HTML 页面
- 需要配合
@ResponseBody才能返回 JSON
📌示例

📌 2. @RestController ------ "我是一个 API 控制器"
- 作用:等同于
@Controller + @ResponseBody - 特点:
- 自动把返回值转成 JSON
- 适合做 前后端分离项目(Vue/Angular/React)
📌示例

- 一句话总结:当用户访问
/user路径时,服务器会返回一个 JSON 格式的用户数据(而不是网页)。
📌 3. @RequestMapping ------ "这个方法处理哪个路径?"
- 作用:绑定 URL 路径到方法
- 可以加在类上或方法上
📌 4. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping ------ "我只处理哪种请求?"
这些是 @RequestMapping 的简化写法,更清晰!
| 注解 | 对应 HTTP 方法 | 用途 |
|---|---|---|
@GetMapping |
GET | 获取数据(查) |
@PostMapping |
POST | 创建数据(增) |
@PutMapping |
PUT | 更新数据(改) |
@DeleteMapping |
DELETE | 删除数据(删) |
📌示例
java
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/user/{id}") // GET /api/user/1
public User getUser(@PathVariable Long id) {
return new User("李四", 30);
}
@PostMapping("/user") // POST /api/user
public String createUser(@RequestBody User user) {
System.out.println("创建用户:" + user.getName());
return "success";
}
@PutMapping("/user/{id}") // PUT /api/user/1
public String updateUser(@PathVariable Long id, @RequestBody User user) {
return "更新成功";
}
@DeleteMapping("/user/{id}") // DELETE /api/user/1
public String deleteUser(@PathVariable Long id) {
return "删除成功";
}
}
📌 5. @RequestBody ------ "请求体里的 JSON 怎么读?"
- 作用:把前端发来的 JSON 数据 自动转换成 Java 对象
- 必须配合
@PostMapping等使用

- 总结:这段代码定义了一个接收JSON数据的POST接口:当客户端(如前端、POSTMAN)发送一个包含用户信息的JSON到/user路径时,Spring会自动把JSON转换为Use对象,交给你处理
📌6. @ResponseBody ------ "返回值怎么变成 JSON?"
- 作用:把方法返回的对象 自动转成 JSON 字符串
- 如果用了
@RestController,就不用写了(默认开启)
📌7、总结对比
| 注解 | 作用 | 什么时候用 |
|---|---|---|
@Controller |
处理请求,返回页面 | 做传统 Web 项目(JSP) |
@RestController |
处理请求,返回 JSON | 做前后端分离项目(Vue/React) |
@RequestMapping |
绑定 URL 路径 | 通用,可写在类或方法上 |
@GetMapping |
处理 GET 请求 | 查询数据 |
@PostMapping |
处理 POST 请求 | 提交表单、上传数据 |
@RequestBody |
读取请求体中的 JSON | 接收前端发来的数据 |
@ResponseBody |
把返回值转成 JSON | 和 @Controller 搭配使用 |
| 注解 | 作用 |
|---|---|
@Controller |
注册一个控制器,处理请求,返回页面 |
@RestController |
注册一个 API 控制器,返回 JSON(等于 @Controller + @ResponseBody) |
@RequestMapping |
绑定 URL 路径 |
@GetMapping |
处理 GET 请求 |
@PostMapping |
处理 POST 请求 |
@PutMapping |
处理 PUT 请求 |
@DeleteMapping |
处理 DELETE 请求 |
@RequestBody |
读取请求体中的 JSON |
@ResponseBody |
把返回值转成 JSON |
@Service |
注册一个服务类(Bean),供 Controller 使用 |
🎯若依中Spring MVC注解
Ruoyi 是一个 前后端分离 的权限管理系统,后端完全通过 RESTful API 返回 JSON。
因此,它大量使用:
@RestController(不是@Controller)@GetMapping/@PostMapping等 HTTP 方法映射@RequestBody接收前端传来的 JSON@PathVariable获取 URL 中的参数- 返回统一结果封装类
AjaxResult
💡 所有 Controller 都放在
com.ruoyi.web.controller包下
📌示例:实现一个 "用户管理"接口 ,功能包括:
- 查询部门详情(GET)
- 新增部门(POST,接收 JSON)
1️⃣ 第一步:定义统一返回结果类

源码:ruoyi-common.core.domain.AjaxResult
java
package com.ruoyi.common.core.domain;
import java.util.HashMap;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.utils.StringUtils;
/**
* 操作消息提醒
*
* @author ruoyi
*/
public class AjaxResult extends HashMap<String, Object>
{
private static final long serialVersionUID = 1L;
/** 状态码 */
public static final String CODE_TAG = "code";
/** 返回内容 */
public static final String MSG_TAG = "msg";
/** 数据对象 */
public static final String DATA_TAG = "data";
/**
* 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
*/
public AjaxResult()
{
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
*/
public AjaxResult(int code, String msg)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
}
/**
* 初始化一个新创建的 AjaxResult 对象
*
* @param code 状态码
* @param msg 返回内容
* @param data 数据对象
*/
public AjaxResult(int code, String msg, Object data)
{
super.put(CODE_TAG, code);
super.put(MSG_TAG, msg);
if (StringUtils.isNotNull(data))
{
super.put(DATA_TAG, data);
}
}
/**
* 返回成功消息
*
* @return 成功消息
*/
public static AjaxResult success()
{
return AjaxResult.success("操作成功");
}
/**
* 返回成功数据
*
* @return 成功消息
*/
public static AjaxResult success(Object data)
{
return AjaxResult.success("操作成功", data);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @return 成功消息
*/
public static AjaxResult success(String msg)
{
return AjaxResult.success(msg, null);
}
/**
* 返回成功消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 成功消息
*/
public static AjaxResult success(String msg, Object data)
{
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
/**
* 返回错误消息
*
* @return
*/
public static AjaxResult error()
{
return AjaxResult.error("操作失败");
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(String msg)
{
return AjaxResult.error(msg, null);
}
/**
* 返回错误消息
*
* @param msg 返回内容
* @param data 数据对象
* @return 警告消息
*/
public static AjaxResult error(String msg, Object data)
{
return new AjaxResult(HttpStatus.ERROR, msg, data);
}
/**
* 返回错误消息
*
* @param code 状态码
* @param msg 返回内容
* @return 警告消息
*/
public static AjaxResult error(int code, String msg)
{
return new AjaxResult(code, msg, null);
}
/**
* 方便链式调用
*
* @param key 键
* @param value 值
* @return 数据对象
*/
@Override
public AjaxResult put(String key, Object value)
{
super.put(key, value);
return this;
}
}
2️⃣ 第二步:定义实体类(用户)

3️⃣ 第三步:定义 Service 接口与实现(供 Controller 调用)


4️⃣ 第四步:定义 Controller(核心!Spring MVC 注解集中地)

5️⃣ 第五步:Spring Boot 启动类(环境初始化)

总结:
- 所有 Controller 都是
@RestController - 路径统一用
@RequestMapping("/system/xxx") - 参数用
@PathVariable和@RequestBody - 返回值全是
AjaxResult