RuoYi 项目中 Spring IOC/DI 和 Spring MVC 注解使用分析
一、前言
本文通过分析若依(RuoYi)开源项目,深入学习 Spring IOC、DI 和 Spring MVC 注解的实际应用。 RuoYi 是一个基于 Spring Boot 的权限管理系统,代码规范,非常适合学习 Spring 框架的使用。
本文将从以下几个方面进行分析: 1. Spring 环境启动流程 2. Spring IOC 和 DI 注解的使用 3. Spring MVC 注解的使用 4. 拓展:接口多实现类的自定义注入
二、Spring 环境启动
2.1 启动类分析

2.1.1注解说明:
-
@SpringBootApplication
- 这是 Spring Boot 的核心注解,是一个组合注解
- 包含三个注解:
@SpringBootConfiguration:标记为配置类@EnableAutoConfiguration:启用自动配置@ComponentScan:自动扫描组件
-
exclude = { DataSourceAutoConfiguration.class }
- 排除数据源自动配置
- 原因:RuoYi 使用了 Druid 多数据源,需要自定义配置
-
SpringApplication.run()
- 启动 Spring 容器
- 参数1:主配置类
- 参数2:命令行参数
2.2启动流程:
启动 main 方法
↓
加载 @SpringBootApplication 注解
↓
扫描所有带 @Component、@Service、@Repository、@Controller 的类
↓
创建 Bean 并放入 IOC 容器
↓
处理 @Autowired、@Resource 等依赖注入
↓
启动内置 Tomcat 服务器
↓
应用启动成功
三、Spring IOC 注解使用(创建对象)
3.1 使用 @Configuration + @Bean 创建对象


3.1.1注解说明:
-
@Configuration
- 标记这是一个配置类,相当于 XML 配置文件
- Spring 会在启动时加载这个类
- 类中的 @Bean 方法会被执行
-
@Bean(name = "captchaProducer")
- 将方法返回的对象注册为 Spring Bean
- Bean 的名称为 "captchaProducer"
- 这个 Bean 可以在其他地方通过 @Resource 或 @Autowired 注入
-
@Bean(name = "captchaProducerMath")
- 注册第二个验证码生产者 Bean
- Bean 名称为 "captchaProducerMath"
- 用于生成数学运算验证码
3.1.2 为什么要创建两个 Bean?
①captchaProducer:生成普通字符验证码(如:abcd)
②captchaProducerMath:生成数学运算验证码(如:1+2=?)
③系统可以根据配置选择使用哪种验证码
3.1.3 IOC 容器中的 Bean:
Spring IOC 容器
├── captchaProducer (DefaultKaptcha 对象)
└── captchaProducerMath (DefaultKaptcha 对象)
3.2 使用 @Component 创建对象

3.2.1 注解说明:
-
@Component
- 通用组件注解,将 RedisCache 类注册为 Spring Bean
- Spring 启动时会自动创建这个类的实例
- Bean 名称默认为类名首字母小写:redisCache
-
@Autowired
- 自动注入 RedisTemplate Bean
- Spring 会从 IOC 容器中查找 RedisTemplate 类型的 Bean 并注入
3.2.2 类的作用:
①封装 Redis 操作
②提供缓存的增删改查方法
③简化 Redis 的使用
3.3 使用 @Service 创建对象

3.3.1 注解说明:
-
@Service
- 业务逻辑层注解,将 SysConfigServiceImpl 注册为 Spring Bean
- 本质上也是 @Component,但语义更明确
- 表示这是一个业务逻辑处理类
-
@Autowired
- 注入 SysConfigMapper(数据访问层)
- 注入 RedisCache(缓存工具类)
3.3.2 类的作用:
①处理系统配置相关的业务逻辑
②先从 Redis 缓存中查询配置
③缓存不存在时从数据库查询并缓存
3.3.3 分层架构:
Controller 层(接收请求)
↓
Service 层(业务逻辑)← SysConfigServiceImpl
↓
Mapper 层(数据访问)
四、Spring DI 注解使用(依赖注入)
4.1 使用 @Resource 按名称注入

4.1.1注解说明:
-
@Resource(name = "captchaProducer")
- 按名称注入 Bean
- 从 IOC 容器中查找名称为 "captchaProducer" 的 Bean
- 这个 Bean 是在 CaptchaConfig 中通过 @Bean 创建的
-
@Resource(name = "captchaProducerMath")
- 按名称注入 Bean
- 从 IOC 容器中查找名称为 "captchaProducerMath" 的 Bean
- 这个 Bean 是在 CaptchaConfig 中通过 @Bean 创建的
-
@Autowired
- 按类型自动注入
- 注入 RedisCache 和 ISysConfigService
4.2 @Resource 和 @Autowired 的区别:
| 注解 | 注入方式 | 来源 | 使用场景 |
| @Resource | 按名称注入 | JDK标准注解 | 有多个相同类型的Bean时 |
| @Autowired | 按类型注入 | Spring注解 | 只有一个该类型的Bean时 |
4.3依赖注入流程:
Spring 容器启动
↓
创建 CaptchaController 对象
↓
发现 @Resource(name = "captchaProducer")
↓
从 IOC 容器中查找名为 "captchaProducer" 的 Bean
↓
将 Bean 注入到 captchaProducer 字段
↓
发现 @Autowired
↓
从 IOC 容器中查找 RedisCache 类型的 Bean
↓
将 Bean 注入到 redisCache 字段
↓
依赖注入完成,对象可以使用
五、Spring MVC 注解使用
PPT 中讲解了 @RestController、@GetMapping、@RequestBody 等基础的路由和请求体注解。在 RuoYi 项目的实际开发中,为了设计更加优雅的 RESTful 风格 API,经常会用到 PPT 中未列出的拓展注解——@PathVariable。
5.1 使用 @PathVariable 动态绑定路径参数

5.1.1 注解说明:
@PathVariable
作用: 将 HTTP 请求 URL 路径中的模板变量(如上方的 /{userId}),动态解析并绑定到处理函数的参数上。
属性 value: 指定要绑定的 URL 变量名称("userId")。
属性 required: 设为 false 表示该参数不是必传项(因为映射路径有 / 和 /{userId} 两种情况)。
5.1.2 完整请求处理流程(包含 Spring 启动):
Spring Application 启动
↓
内嵌 Tomcat 服务器启动,DispatcherServlet 准备就绪
↓
Spring MVC 扫描带 @RestController 的类,将 SysUserController 注册到容器
↓
解析 @GetMapping,将路由 "/system/user/{userId}" 与 getInfo 方法建立映射关系
↓
前端发起请求:GET http://localhost/system/user/1001
↓
DispatcherServlet 拦截请求并匹配路由
↓
解析路径参数:@PathVariable 自动提取 URL 中的 "1001",转换为 Long 类型
↓
将 1001 注入到形参 userId 中,进入函数执行业务逻辑
↓
返回 JSON 结果给前端
六、拓展:接口多实现类的自定义注入
6.1 问题场景与操作步骤
当一个接口(例如 ISysUserService)存在多个实现类时,如果在 Controller 中直接使用 @Autowired(默认按类型注入),Spring 容器会因为找到多个相同类型的 Bean 而陷入迷茫,从而抛出异常。
要解决这个问题,我们需要结合名称注解进行精确制导:

此处左边是我自己写的一个自定义 Service 实现类(带 @Service("myCustomUserService")),右边是 Controller 里使用 @Resource(name = "myCustomUserService") 注入的代码。
步骤 1:定义并注册 Bean(为自定义实现类起个特定名字)
1.在 IDEA 的左侧项目目录中,找到这个路径:ruoyi-system -> src -> main -> java -> com.ruoyi.system.service.impl
2.在这个 impl 文件夹上右键,选择 New -> Java Class,给它起名叫MyCustomUserServiceImpl,你们也可以选择自己起个名字。
3.定义并注册bean,如下面代码所示(你们通过继承原有的类来偷懒,这样就不用重写那几十个接口方法了):
// 使用 @Service 注解,并显式指定 Bean 的名称为 "myCustomUserService"
@Service("myCustomUserService")
public class MyCustomUserServiceImpl implements ISysUserService {
// ... 自定义的重写逻辑
}
步骤 2:注入自己实现的 Bean(按名称注入)
1.找到路径:ruoyi-admin -> src -> main -> java -> com.ruoyi.web.controller.system -> SysUserController
2.打开 SysUserController,在代码的开头部分,你会看到原来写的是 @Autowired。
放弃单纯的类型匹配,改用按名称匹配,确保注入的是我们自己的实现类。
3.把原来的注入代码稍作修改,可以参考下面代码。
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {
// 结合具体名称进行精确注入
@Resource(name = "myCustomUserService")
private ISysUserService userService;
// 或者使用 @Autowired 配合 @Qualifier
// @Autowired
// @Qualifier("myCustomUserService")
// private ISysUserService userService;
}
6.2 现实意义分析
很多成熟的开源框架(如 RuoYi)已经提供了完善的基础接口实现。但在实际的 CSMD (Controller, Service, Model/Mapper, DAO/Data) 分层架构开发中,我们往往需要针对特定的定制化需求重写核心的 Service 逻辑。
如果直接修改框架原本的源码,会导致后续框架升级困难。而利用 Spring 这种“多实现类 + 指定 Bean 名称注入”的机制,我们可以在完全不触碰框架原有 Controller 和原生 Service 源码的前提下,仅通过新增一个带有特定 @Service("自定义名称") 的实现类,并在业务调用处修改注入名称,就能实现底层业务逻辑的无缝替换。这极大地提高了代码的灵活性,完美契合了面向对象设计中的“开闭原则”(对扩展开放,对修改关闭)。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)