当前位置: 首页 > news >正文

Spring IOC/DI 与 MVC 从入门到实战

目录

🎯首先学习Spring IOC/DI

1、Spring IOC/DI整体框架

1.1 核心思想:

1.2 两个关键字:

1.3 对象之间的依赖关系

2、真实案例(对比传统java和Spring(IOC和DI)):

2.1  ❌ 场景一:传统java没有Spring——“自己动手,丰衣足食”

2.1.1、定义一个服务类

2.1.2、使用方法

2.2  ✅ 场景二:使用 Spring(IOC + DI)—— “点菜式开发”

2.2.1、定义服务类(加注解)  

2.2.2 、启动Spring容器(配置扫描)

2.2.3、使用方法(从容器中拿对象)——启动类

 3、总结对比

4、 常见问题:

 🎯若依中Spring IOC、DI注解

1、定义实体类

2、定义Service接口

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

4、DI:定义Controller,注入Service

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

6、整个流程:

7、关键总结(Ruoyi中IOC/DI的使用模式)

 🎯Spring MVC

1、🌟 Spring MVC 工作流程

2、注解

📌 1. @Controller —— “我是一个网页控制器”

📌 2. @RestController —— “我是一个 API 控制器”

📌 3. @RequestMapping —— “这个方法处理哪个路径?”

📌 4. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping —— “我只处理哪种请求?”

📌 5. @RequestBody —— “请求体里的 JSON 怎么读?”

 📌6. @ResponseBody —— “返回值怎么变成 JSON?”

 📌7、总结对比

🎯若依中Spring MVC注解

📌示例:实现一个 “用户管理”接口,功能包括:

1️⃣ 第一步:定义统一返回结果类

2️⃣ 第二步:定义实体类(用户)

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

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

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 对象之间的依赖关系

  • 对象之间的依赖关系=一个对象需要另一个对象才能工作(就像你吃饭需要筷子,你依赖筷子)
  • 一个程序中的类需要别的类才能完成任务,这就是 “依赖

在代码中:

@Servicepublic 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、定义一个服务类
//定义一个服务类
//用户服务
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、使用方法
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、定义服务类(加注解)
  
//告诉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容器(配置扫描)
//配置类:告诉Spring从那个包开始找@Compent类
//表示这是一个配置类,相当于以前的xml文件————>作用:告诉Spring这是你的说明书,请按这个来设置容器
@Configuration
//告诉Sring,请从这个包目录开始,自动扫描所有带@Component、@Service、@Controller、@Repository注解的类,把这些类都注册到Spring容器里面
//注册之后Spring就会自动发现这些类,并创建类对象放进容器里
@ComponentScan(basePackages="com.example.service")
public class SpringConfig{//空配置类即可
}
  1. 流程梳理:

    启动程序时,Spring 会:
    • 读取 SpringConfig
    • 开始扫描 com.example.service 包下的类
    • 发现 UserService 和 OrderService,把它们创建成对象,放进容器
    • 当 OrderService 里有 @Autowired private UserService userService; 时 → Spring 自动把 UserService 对象注入进来
    • 程序就可以正常运行了
    • 补充:@Configuration + @ComponentScan 是告诉 Spring:“请从指定包里找出所有带注解的类,把它们变成对象放进来管理。
  2. 为什么需要启动类:

    @Configuration + @ComponentScan 是“配置”阶段,告诉 Spring 去哪找类————但这还不够,我们需要一个“主程序”来启动真正的Spring容器,然后从容器里拿对象使用。
    --因为java程序不会自己运行,必须有人启动他
    --Spring容器不是魔法——它是个普通的java对象,需要人主动创建它,它才会开始工作(IOC /DI)
    --本质:
                ①java是静态语言,代码不会自己跑起来
                ②Spring容器只是一个库(library),它不会在你编译或写代码时自动激活
                ③必须由你的程序主动创建容器实例,它才会开始扫描、注册、注入

2.2.3、使用方法(从容器中拿对象)——启动类
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();}
}

Spring方式的优点
优势说明
解耦OrderService不需要知道UserService怎么创建
灵活替换只要实现相同的接口,换实现不用改一行代码
单例自动管理默认每个Bean是单例,Spring保证线程安全
易于测试单元测试时可轻松注入Mock对象

 3、总结对比

维度传统方式Spring(IOC+DI)
谁创建对象?你自己newSpring 容器创建
谁管理对象?你自己管生命周期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 方法用途
@GetMappingGET获取数据(查)
@PostMappingPOST创建数据(增)
@PutMappingPUT更新数据(改)
@DeleteMappingDELETE删除数据(删)

📌示例

@RestController
@RequestMapping("/api")
public class UserController {@GetMapping("/user/{id}")  // GET /api/user/1public User getUser(@PathVariable Long id) {return new User("李四", 30);}@PostMapping("/user")  // POST /api/userpublic String createUser(@RequestBody User user) {System.out.println("创建用户:" + user.getName());return "success";}@PutMapping("/user/{id}")  // PUT /api/user/1public String updateUser(@PathVariable Long id, @RequestBody User user) {return "更新成功";}@DeleteMapping("/user/{id}")  // DELETE /api/user/1public 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

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 数据对象*/@Overridepublic 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
http://www.dtcms.com/a/585371.html

相关文章:

  • SCNet超算平台DCU异构环境的Ollama启动服务后无法转发公网的问题解决
  • macOS下如何全文检索epub格式文件?
  • 一键配置 macOS 终极终端:iTerm2 + Oh My Zsh 自动化安装脚本
  • 如何在 Mac、Ubuntu、CentOS、Windows 上安装 MySQL 客户端
  • 石景山广州网站建设外贸soho建站多少钱
  • 某观鸟记录中心的爬虫——mitmproxy的简单使用
  • 58同城上海网站建设北京朝阳区房价
  • 金融网络销售怎么找客源公司网站做优化少钱
  • 代码随想录 Q84.分发饼干
  • 11.8 脚本网页 打砖块max
  • 终极笔记应用程序Alexandrie
  • 「嵌」入未来,「式」界无限 · 第5篇:能源电力的智能化跃迁
  • 自动化实践(7.25):把 PsTools 接入 PowerShell / 批处理 / Ansible
  • 太原在线网站建设深圳网站关键词优化
  • AWS Lambda的安全之道:S3静态加密与运行时完整性检查的双重保障
  • 时序数据库选型指南从大数据视角看IoTDB的核心优势
  • 长沙网站建站模板创免费网站
  • dede 门户网站长春建站网站建设
  • Android Hilt 入门教程_传统写法和Hilt写法的比较
  • 【开题答辩全过程】以 个性化宿舍分配管理系统为例,包含答辩的问题和答案
  • wordpress站点制作武威网站制作公司哪个好
  • 【ZeroRange WebRTC】WebRTC 媒体安全:实现原理与应用(深入指南)
  • python3GUI--短视频社交软件 By:Django+PyQt5(前后端分离项目)
  • Rust 练习册 :Raindrops与FizzBuzz变体
  • Home Assistant Z-Pi 800全新硬件打造远距离智能家居体验
  • 易货电商新模式:小本钱撬动大市场,破解实体店“三大愁”
  • 做网站需要多少人网站建设价格很 好乐云seo
  • Java 大视界 -- 基于 Java 的大数据可视化在城市空气质量监测与污染溯源中的应用
  • 《玩转Docker》[应用篇16]:Docker安装部署HomeBox-家庭库存管理
  • 网站用什么布局wordpress怎么使用七牛云储存