Spring IOC&DI(上)

作者:阿武不想上早八日期:2026/2/6

Spring IOC&DI(上)


1. Spring IOC&DI

Spring 是包含了众多工具方法的 IOC 容器

1.1 容器

概念:容器时用来容纳物品的装置。
例子:List/Map -> 数据存储容器;Tomcat -> Web 容器

1.2 IOC

概念:全称:Inversion of Control(控制反转),是 Spring 的核心思想,把对象交给 Spring 管理,就是 IOC 思想。
在这里插入图片描述

总的来说,Spring 就是一个”控制反转“的容器。


2. IOC&DI 介绍

2.1 IOC 介绍

如果我们造一辆车

2.1.1 传统开发

思路:先设计轮子,然后根据轮子设计底盘,再根据底盘设计车身,再根据车身设计一辆整车。
所产生的依赖关系:
在这里插入图片描述

代码实现:
车:

1public class Car {
2    private Framework framework;
3
4    public Car(int size) {
5        this.framework = new Framework(size);
6        System.out.println("car init...");
7    }
8
9    public void run() {
10        System.out.println("car run...");
11    }
12}
13

车身:

1public class Framework {
2    private Bottom bottom;
3
4    public Framework(int size) {
5        this.bottom = new Bottom(size);
6        System.out.println("framework init...");
7    }
8}
9
10

底盘:

1public class Bottom {
2    private Tire tire;
3
4    public Bottom(int size) {
5        this.tire = new Tire(size);
6        System.out.println("bottom init...");
7    }
8}
9

轮胎:

1public class Tire {
2    private int size;
3
4    public Tire(int size) {
5        this.size = size;
6        System.out.println("tire init...,size:" + size);
7    }
8}
9

2.1.2 问题分析

代码可维护性低,假如我们想要对轮子的颜色也有要求,就需要对上层的程序也进行修改。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当底层代码改动后,整个调用链上的所有代码都需要修改。

2.1.3 IOC 程序开发

如果反正设计车辆,依赖关系就会倒置,轮子依赖底盘,底盘依赖车身,车身依赖汽车。
在这里插入图片描述
代码实现:
主程序:

1public class Main {
2    public static void main(String[] args) {
3        Tire tire = new Tire(21);
4        Bottom bottom = new Bottom(tire);
5        Framework framework = new Framework(bottom);
6        Car car = new Car(framework);
7        car.run();
8    }
9}
10

车:

1public class Car {
2    private Framework framework;
3
4    public Car(Framework framework) {
5        this.framework = framework;
6    }
7
8    public void run() {
9        System.out.println("car run...");
10    }
11}
12

车身:

1public class Framework {
2    private Bottom bottom;
3
4    public Framework(Bottom bottom) {
5        this.bottom = bottom;
6        System.out.println("framework init...");
7    }
8}
9

底盘:

1public class Bottom {
2    private Tire tire;
3
4    public Bottom(Tire tire) {
5        this.tire = tire;
6        System.out.println("bottom init...");
7    }
8}
9

轮胎:

1public class Tire {
2    private int size;
3
4    public Tire(int size) {
5        this.size = size;
6        System.out.println("tire init...,size:" + size);
7    }
8}
9

代码经过以上调整,无论底层类如何变化,整个调用链不用做任何变化,这样就完成了代码之间的解耦。

2.1.4 IOC 的优势

资源不由使用双方管理,而由不使用资源的第三方管理的优势在于资源集中管理,实现了资源的可配置和易管理,降低了使用双方的依赖程度。
在这里插入图片描述

2.2 DI 介绍

概念:全称:Dependency Injection(依赖注入),容器在运行期间,动态的为应用程序提供运行时所依赖的资源,称之为依赖注入。
上述代码时通过构造函数的方式,把依赖对象注入到需要使用的对象中的
在这里插入图片描述
IOC是一种思想,DI 就属于具体的实现,DI 是 IOC 的一种实现。


3. IOC & DI 使用

Spring 是一个 IOC 容器,作为容器,那么它就具备两个最基础的功能:存和取,Spring 容器管理的主要是对象,这些对象称为“Bean”,并且交由 Spring 管理,由 Spring 来负责创建和销毁。
我们利用图书管理系统代码来展示 IOC & DI 的使用

1@Repository
2public class BookDao {
3    public List<BookInfo> mockData() {
4        List<BookInfo> bookInfos = new ArrayList<>();
5        for(int i = 1;i <= 15;i++) {
6            BookInfo bookInfo = new BookInfo();
7            bookInfo.setId(i);
8            bookInfo.setBookName("图书" + i);
9            bookInfo.setBookAuthor("作者" + i);
10            bookInfo.setCount(new Random().nextInt(100));
11            bookInfo.setPrice(new BigDecimal(new Random().nextInt(100)));
12            bookInfo.setPublish("出版社" + i);
13            bookInfo.setStatus(i%5==0?2:1);
14            bookInfos.add(bookInfo);
15        }
16        return bookInfos;
17    }
18}
19
1@Service
2public class BookService {
3    @Autowired
4    private BookDao bookDao;
5
6    public List<BookInfo> getList() {
7        List<BookInfo> bookInfos = bookDao.mockData();
8        for(BookInfo bookInfo : bookInfos) {
9            if(bookInfo.getStatus() == 1) {
10                bookInfo.setStatusCN("可借阅");
11            } else {
12                bookInfo.setStatusCN("不可借阅");
13            }
14        }
15        return bookInfos;
16    }
17}
18
1@RestController
2@RequestMapping("/book")
3public class BookController {
4    @Autowired
5    private BookService bookService;
6
7    @RequestMapping("/getList")
8    public List<BookInfo> getList() {
9        List<BookInfo> bookInfos = bookService.getList();
10        return bookInfos;
11    }
12}
13

运行程序
在这里插入图片描述


4. IOC 详解

IOC 控制反转就是将对象的控制权交给 Spring 的 IOC 容器,由 IOC 容器创建及管理对象,就是 Bean 的存储。

4.1 Bean 的存储

把对象交给 IOC 容器管理,需要两类注解
(1)类注解:@Controller、@Service、@Repository、@Component、@Configuration
(2)方法注解:@Bean

4.1.1 @Controller

使用 @Controller 存储 bean 代码

1@Controller
2public class UserController {
3    public void sayHello() {
4        System.out.println("hello");
5    }
6}
7

从 Spring 容器中获取对象
ConfigurableApplicationContext 类继承了 ApplicationContext 类,ApplicationContext 类 又继承了BeanFactory类,BeanFactory 类提供了大量获取 bean 的方法

在这里插入图片描述
在这里插入图片描述

1@SpringBootApplication
2public class SpringIocDemoApplication {
3
4	public static void main(String[] args) {
5		ConfigurableApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
6		UserController userController = context.getBean(UserController.class);
7		userController.sayHello();
8	}
9}
10

观察运行结果,发现成功从 Spring 中获取到 Controller 对象,并执行 Controller 的 sayHello 方法
在这里插入图片描述

如果把 @Controller 删掉,再观察运行结果
在这里插入图片描述
报错信息显示:找不到类型是:com.example.demo.controller.UserController 的 bean

获取 bean 对象的其他方式

ApplicationContext 也提供了其他获取 bean 的方式,ApplicationContext 获取 bean 对象的功能,是父类 BeanFactory 提供的功能
在这里插入图片描述

Bean 命名的约定
官方文档:https://docs.spring.io/spring-framework/reference/core/beans/definition.html#beans-beanname
在这里插入图片描述
命名约定使用 Java 标准约定作为实例字段名,bean 名称以小写字母开头,然后使用驼峰式大小写。当有多个字符并且第一个和第二个字符都是大写时,将保留原始的大小写。

根据这个命名规则,我们来获取 bean

1@SpringBootApplication
2public class SpringIocDemoApplication {
3	public static void main(String[] args) {
4		ConfigurableApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
5		UserController userController1 = context.getBean(UserController.class);
6		UserController userController2 = (UserController) context.getBean("userController");
7		UserController userController3 = context.getBean("userController", UserController.class);
8		System.out.println(userController1);
9		System.out.println(userController2);
10		System.out.println(userController3);
11	}
12}
13

运行结果
在这里插入图片描述

4.1.2 @Service

使用 @Service 存储 bean 的代码

1@Service
2public class UserService {
3    public void sayHi() {
4        System.out.println("Hi");
5    }
6}
7

读取 bean 代码

1@SpringBootApplication
2public class SpringIocDemoApplication {
3	public static void main(String[] args) {
4		ConfigurableApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
5		UserService userService = context.getBean(UserService.class);
6		userService.sayHi();
7	}
8}
9

观察结果,发现成功从 Spring 中获取到 UserService 对象,并执行了 sayHi 方法
在这里插入图片描述

4.1.3 @Repository

使用 @Repository 存储 bean 的代码

1@Repository
2public class UserRepository {
3    public void sayHi() {
4        System.out.println("Hi");
5    }
6}
7

读取 bean 代码

1@SpringBootApplication
2public class SpringIocDemoApplication {
3	public static void main(String[] args) {
4		ConfigurableApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
5		UserRepository userRepository = context.getBean(UserRepository.class);
6		userRepository.sayHi();
7	}
8}
9
10

运行结果
在这里插入图片描述

4.1.4 @Component

使用 @Component 存储 bean

1@Component
2public class UserComponent {
3    public void sayHi() {
4        System.out.println("Hi");
5    }
6}
7

读取 bean 代码

1@SpringBootApplication
2public class SpringIocDemoApplication {
3	public static void main(String[] args) {
4		ConfigurableApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
5		UserComponent userComponent = context.getBean(UserComponent.class);
6		userComponent.sayHi();
7	}
8}
9

运行结果:
在这里插入图片描述

4.1.5 @Configuration

使用 @Configuration 存储 bean 的代码

1@Configuration
2public class UserConfiguration {
3    public void sayHi() {
4        System.out.println("Hi");
5    }
6}
7

读取 bean 代码

1@SpringBootApplication
2public class SpringIocDemoApplication {
3	public static void main(String[] args) {
4		ConfigurableApplicationContext context = SpringApplication.run(SpringIocDemoApplication.class, args);
5		UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);
6		userConfiguration.sayHi();
7	}
8}
9

运行结果
在这里插入图片描述

4.2 类注解的关系

@Controller:控制层,接收请求,对请求进行处理,并进行响应。
@Service:业务逻辑层,处理具体的业务逻辑。
@Repository:数据访问层,负责数据访问操作。
@Configuration:配置层,处理项目中的一些配置信息。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看@Controller、@Service、@Repository、@Configuration 等注解的源代码发现,这些注释里面都有一个 @Component 注解,说明他们本身都属于 @Component 的子类,@Controller、@Service、@Repository、@Configuration 被称为衍生注解。


Spring IOC&DI(上)》 是转载文章,点击查看原文


相关推荐


【学习笔记】C++(1)
贺一航【Niki】2026/1/28

C++学习笔记 一、基础 1、类型表示范围 2、cout 3、char 4、string 5、逻辑运算符 6、枚举 7、随机数 8、数组 9、其他 一、基础 1、类型表示范围 类型 字节数 位宽 十进制范围(大约) 具体值范围 char 1


【AI大模型开发】-基于FAISS的语义搜索系统(实战)
Java后端的Ai之路2026/1/19

向量数据库实战:基于FAISS的语义搜索系统 一、项目概述 1.1 什么是向量数据库? 向量数据库是一种专门用于存储、索引和检索高维向量数据的数据库系统。在AI领域,向量通常是指通过预训练模型(如Transformer)将文本、图像等非结构化数据转换而成的数值表示(Embedding)。 1.2 项目背景 本项目展示了如何使用阿里云百炼Embedding API生成文本向量,并结合FAISS(Facebook AI Similarity Search)构建一个简单但功能完整的语义搜索系统。 1.


Claude Skills:Agent 能力扩展的新范式
清沫2026/1/11

为什么需要 Skills? 2025 年被称为智能体元年。各类 Agent、子 Agent、MCP 工具及自动化流水线迅速出现,让 AI 可以接手越来越多真实工作。比如 Claude Code 推出的 Agent 模块,或通过可视化平台、LangChain 开发的各种工具。 随着智能体功能增强,需要更具可组合性、可扩展性和可移植性的方法,为它们配备特定领域专业知识。这促使智能体 Skills 诞生:智能体可动态发现并加载包含指令、脚本和资源的文件夹,从而更好完成特定任务。 什么是 Skills?


2025年度总结之-如何构建 2025 专属的 GitHub AI 项目情报库
CoderJia_2026/1/3

背景 为什么做 为了更好地追踪 2025 年涌现的 AI 开源项目,我经常浏览 Github 热榜 并整理分享。但手动查阅难免会有遗漏,为此,我计划开发一套自动化工具来采集 Github 热榜数据,旨在辅助个人技术积累的同时,也为博客内容提供持续的素材来源。下文将详细介绍我的技术实现思路,若有设计不足之处,恳请各位读者指正。 如何制作 在该流程的初始阶段,核心任务是构建针对 GitHub 热榜(Trending)页面的数据采集机制。需要分别按照日(Daily)、周(Weekly)及月(M


从字符游戏到 CPU 指令集:一道算法题背后的深度思维跃迁
ToddyBear2025/12/24

"Simplicity is the ultimate sophistication." — Leonardo da Vinci 前言:很多时候,一道看似简单的算法题,不仅是代码能力的试金石,更是计算机底层思维的显微镜。本文记录了一次关于“查找 K-th 字符”问题的深度探讨。我们不满足于“做出来”,而是试图通过逆向工程,从直觉出发,推导出数学原理,最终触达硬件指令集的设计哲学。 🟢 第一部分:面试极速备忘录 (Executive Summary) 为了方便日后快速回顾(如面试前 5


5 分钟快速入门 Gitlab CI/CD
yuguo.im2025/12/16

🚀 快速掌握 GitLab CI/CD:自动化你的开发流程 GitLab CI/CD 是一个功能强大的工具,它内置于 GitLab 中,用于自动化你的软件构建、测试和部署流程。如果你希望提升开发效率、减少人为错误并实现持续集成/持续部署(CI/CD),那么掌握它至关重要。 本文将通过最核心的概念、最简单的配置,带你快速入门 GitLab CI/CD。 核心概念:理解 GitLab CI 的基石 在编写你的第一个配置文件之前,理解以下几个关键概念是掌握 GitLab CI 的前提: 1. 配置


这5个AI文本可视化工具太强了!一键把文本转信息图、流程图等多种可视化形式!PPT秒变高级!(建议收藏)
程序员X小鹿2025/12/8

大家好,我是X小鹿。 前几天被读者问到了「文本可视化」工具,趁着周末,整理了下之前体验过的几款还不错的 AI 工具。 这些 AI 工具都可以一键将枯燥的文本,转化为精美信息图、数据图、卡片等形式。 不管是在项目汇报中插入,还是用于 PPT 配图、文章配图、生成科普图文、读书笔记卡片、自媒体图文创作等场景,都是可以的。 下面分享 5 个目前国内外用得较多「文本可视化」工具。 有需要的可以保存下,早晚用得上~ 一、Seede AI 第一个,Seede AI,一款适合普通人上手的 AI 设计工具,国内


Rokid AI眼镜:连接现实与数字的桥梁,探索下一代智能应用开发
倔强的石头_2025/11/28

@[toc] 前言:当AI遇上AR,未来触手可及 增强现实(AR)技术长久以来都被视为下一代计算平台,它承诺将数字信息无缝叠加到物理世界之上,从而彻底改变我们与信息交互的方式。然而,要将这一愿景变为现实,离不开一个强大、易用且充满活力的开发生态。Rokid AI眼镜及其配套的SDK,正是这样一个旨在赋能开发者的平台,它为我们打开了通往“空间互联网”时代的大门。 本文将聚焦于AI Glasses实践应用,以一个具体的工业场景——AI工业装配助手为例,深入探讨如何利用Rokid平台提供的能力,从概念


Kafka 生产者与消费者配置详解
倚肆2026/2/15

Kafka 生产者与消费者配置详解 一、DefaultKafkaProducerFactory 生产者配置详解 配置项示例值作用说明调优建议ProducerConfig.BOOTSTRAP_SERVERS_CONFIG"localhost:9092"Kafka 集群地址列表,生产者通过此地址发现集群。配置多个地址(用逗号分隔)以提高可用性。ProducerConfig.KEY_SERIALIZER_CLASS_CONFIGStringSerializer.class消息键的序列化器。键用于分区


326. Java Stream API - 实现自定义的 toList() 与 toSet() 收集器
yaoxin5211232026/2/23

文章目录 326. Java Stream API - 实现自定义的 `toList()` 与 `toSet()` 收集器📦 实现一个自定义 `toList()` 收集器🚀 使用我们的 `ToList` 收集器🔄 将其改造成 `toSet()` 收集器✅ 修改 1:使用 `HashSet` 作为容器✅ 修改 2:声明该收集器是无序的 🧪 `ToSet` 收集器完整实现示例🎯 总结一下关键点🧠 小贴士 326. Java Stream API - 实现自定义的 toL

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客