news 2026/5/8 16:57:48

认识Spring IoC

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
认识Spring IoC

目录

  • 前言
  • 1. 了解Spring
  • 2. IoC
  • 3. 注解
  • 4. Bean
  • 5. 了解DI
  • 总结

前言

通过本篇文章你将了解到Spring IoC的思想、五大类注解、方法注解,DI。


1. 了解Spring

Spring被称为一个框架,有着庞大的社区,支持很多应用场景。
简单来说就是一个包含了众多对象的容器。
不过这里的容器有一个前缀,叫做IoC。
也就是IoC容器。

容器这个词没那么高深,我们日常生活中经常能看见。
容器嘛就是装东西的。
比如一瓶矿泉水,里面的水是溶剂,空瓶子就是容器。
化学实验室里的烧杯也是一个容器。
我们说Spring是一个容器,只不过是把这个词语稍微抽象了一点。以前我们需要自己去new一个对象,现在Spring将一个个的对象(Object)当作溶剂。Spring把它们装在一起,帮我们统一管理。
再比如,我们使用的HashMap用来存储数据,它也是一个容器。


2. IoC

Spring IoC是Spring中一个比较重要的思想,其中另一个重要的思想是AOP。

这里我们先了解IoC是什么。
首先IoC全称叫做Inversion of Control。翻译过来就是控制反转。
这里的控制可以理解为,对象的控制权。
反转也就是白的变成黑的,主动变成被动。
所以控制反转就是掌握对象创建与销毁的人改变了。

再举出一个例子,一个小公司。
产品研发,人员招聘…这些事情都可以由老板一个人做。
等到公司规模扩大,老板就会把招聘这个事情分出去,让HR来做。
把产品研发交给技术团队去做。
看,掌管人员招聘这个事情的人就变了,由最初的老板控制变为现在的HR控制。

所以Spring IoC就是将对象的控制权转移到Spring上,由Spring来决定对象的创建与销毁。

我们再通过代码来体会这个反转思想。

publicclassNewCarExample{publicstaticvoidmain(String[]args){Carcar=newCar();car.run();}/** * 汽车对象 */staticclassCar{privateFrameworkframework;publicCar(){// 直接在构造函数中 new 下层依赖,导致高耦合framework=newFramework();System.out.println("Car init....");}publicvoidrun(){System.out.println("Car run...");}}/** * 车身类 */staticclassFramework{privateBottombottom;publicFramework(){bottom=newBottom();System.out.println("Framework init...");}}/** * 底盘类 */staticclassBottom{privateTiretire;publicBottom(){tire=newTire();System.out.println("Bottom init...");}}/** * 轮胎类 */staticclassTire{publicTire(){System.out.println("Tire init...");}}}

造车之前我们得将车身造出来,建造车身又得建造底盘…
这样就形成了这样的一个关系:车->车身->底盘->轮胎。
这种写法的耦合度是非常高的。

我们从中选择一个类来具体研究

staticclassBottom{privateTiretire;publicBottom(){tire=newTire();System.out.println("Bottom init...");}}

这个Bottom的建造依赖于Tire这个对象,我们就说Tire是Bottom的一个依赖。
这个Tire是在Bottom的构造方法里面创建出来的,也就是说,Tire这个对象的存活,什么时候创建、销毁,完全由Bottom这个对象决定。

我们再来看另一种写法。

publicclassNewCarExample{publicstaticvoidmain(String[]args){// --- Main 方法作为容器,负责“控制”对象的生命周期和依赖关系 ---// 1. 先生产最底层的零件Tiretire=newTire(18);// 假设现在轮胎可以指定尺寸了// 2. 将零件注入到上一层组件中 (构造方法注入)Bottombottom=newBottom(tire);// 3. 继续向上注入Frameworkframework=newFramework(bottom);// 4. 最后组装成汽车Carcar=newCar(framework);// 5. 运行car.run();}/** * 汽车对象 */staticclassCar{privateFrameworkframework;// IoC:通过构造函数注入依赖,不再自己 newpublicCar(Frameworkframework){this.framework=framework;System.out.println("Car init....");}publicvoidrun(){System.out.println("Car run...");}}/** * 车身类 */staticclassFramework{privateBottombottom;publicFramework(Bottombottom){this.bottom=bottom;System.out.println("Framework init...");}}/** * 底盘类 */staticclassBottom{privateTiretire;publicBottom(Tiretire){this.tire=tire;System.out.println("Bottom init...");}}/** * 轮胎类 */staticclassTire{privateintsize;publicTire(intsize){this.size=size;System.out.println("Tire init, size: "+size);}}}

这个写法就是利用了IoC思想,对象的控制权属于main这个方法,
所有对象都在main里面创建。


3. 注解

好了,IoC思想我们已经体会到了,接下来看看如何在Spring中用上。

这是一个类注解,当你将这个注解添加到类上方时,Spring就会管理这个类,并创建一个对象出来。

@Controller// 将对象存储到 Spring 中publicclassUserController{publicvoidsayHi(){System.out.println("hi,UserController...");}}

当Spring运行的时候,这个UserController对象就已经被创建出来了。

既然对象已经被创建出来了,那我们该怎么验证(或者获取)它呢?毕竟眼见为实对吧。

@SpringBootApplicationpublicclassIoCDemoApplication{//测试Beanpublicstaticvoidmain(String[]args){ApplicationContextcontext=SpringApplication.run(IoCDemoApplication.class,args);UserControllerbean1=context.getBean(UserController.class);bean1.sayHi();//控制台输出hi,UserController...}

其中这一段代码你就理解为获取Spring中的应用程序上下文即可。
这里的上下文也可以理解为拿到Spring这个容器。

ApplicationContextcontext=SpringApplication.run(IoCDemoApplication.class,args);

这一段代码就是从上下文(容器)中获取一个类型为UserController的对象。

UserControllerbean1=context.getBean(UserController.class);

除了Controller这一个类注解,还有其他四个Configuration, Component, Service, Repository。这四个类注解的使用方式几乎可以说是一样的,这里就不演示了。

但是我们要来看看这些注解之间的区别。
在三层架构中,@Controller 代表控制层,负责接收前端的请求;
@Service 是业务层,负责对业务逻辑和数据进行处理;
@Repository 是数据层,主要面向数据库层面的操作;
@Configuration 是配置层,先按下不表。

为什么有这么多功能相似的注解呢?这就和每个省市都有自己的车牌号前缀是一样的道理。

车牌号都是唯一的,用来标识一辆车。但为什么还要设置不同的车牌开头呢?
比如陕西的车牌号是【陕A/B/C…】,北京的车牌号是【京A/B/C…】。通过车牌开头,我们一眼就能知道这辆车是哪个地区的。
注解也是一样,它们都能把对象存进Spring,但不同的注解能让我们一眼看清这个类是属于哪一层(控制层/业务层/数据层)的。

比较重要的区别是Controller不能够和其他注解混用,不然当你输入URL时浏览器页面会报404。

@RequestMapping("/UserController")@Controller//@Configuration@ResponseBodypublicclassUserController{@RequestMapping("/print")publicStringprint(){return"使用 UserController";}}

正常结果

错误代码

@RequestMapping("/UserController")@Controller@ConfigurationpublicclassUserController{@RequestMapping("/print")publicStringprint(){return"使用 UserController";}}

错误结果


4. Bean

在前面的内容里,我们一直用“对象”这个词。但在 Spring 的世界里,被 Spring 容器管理的对象有一个专属的高级名字——Bean(Java Bean)

你可以这么理解:如果在外面,它就是一个普普通通的 Java 对象(Object);一旦它被贴上@Controller@Service等注解,被招进了 Spring 容器,它就摇身一变成为了Spring Bean。就像一个普通人,入职了公司,就成了公司的“打工人”一样。

我们前面讲的@Controller等五大类注解,是贴在上面的。但如果你不想把整个类都交给 Spring,只想把类里面的某个方法的返回值交给 Spring 管理呢?

这时候就要用到我们前言里提到的方法注解:@Bean了。

@Configuration// 通常 @Bean 要配合 @Configuration 一起使用publicclassAppConfig{// 使用 @Bean 注解,告诉 Spring:把这个方法的返回值当成一个 Bean 存起来!@BeanpublicUseruser(){Useruser=newUser();user.setName("张三");user.setAge(18);returnuser;}}

这样,一个名字叫张三的 User 对象(Bean)就被存进 Spring 容器里了,随时待命!


5. 了解DI

现在,我们的 Spring 容器里已经装满了各种各样的 Bean(对象)了。但程序要跑起来,对象和对象之间是需要互相配合的。

比如,控制层的UserController想要调用业务层的UserService
如果是以前,我们要在UserController里面自己去new UserService()
有了 Spring 之后呢?既然它们都在容器里,难道每次都要写一串context.getBean(UserService.class)吗?那也太麻烦了。

这时候,就轮到DI(Dependency Injection,依赖注入)了。

很多人容易把 IoC 和 DI 搞混。其实很简单:

  • IoC 是一种思想(把控制权交出去)。
  • DI 是这种思想的具体实现手段(怎么把需要的对象拿过来用)。

Spring 提供了一个超级好用的注解:@Autowired。只要贴上它,Spring 就会自动把你要的对象给你“注入”进来。

我们来看看代码有多简洁:

@ControllerpublicclassUserController{// 划重点:贴上 @Autowired,Spring 就会自动从容器里找 UserService 塞给你!@AutowiredprivateUserServiceuserService;publicvoidsayHi(){System.out.println("hi, UserController...");// 直接用 userService,完全不需要 new!// userService.doService();}}

总结

  1. 理解 IoC 思想:创建和销毁对象的“控制权”交给了 Spring 容器,让 Spring 来帮我们统一管理,这就是控制反转
  2. 存入 Bean 对象:通过注解我们可以轻松地把对象装进 Spring 容器里。
  3. 使用 DI 依赖注入:对象存进去了还得互相配合。通过@Autowired注解自动把我们需要依赖的 Bean “注入”到我们的代码中。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 16:56:58

Dhizuku:Android设备所有者权限共享架构的技术实现与安全应用

Dhizuku:Android设备所有者权限共享架构的技术实现与安全应用 【免费下载链接】Dhizuku A tool that can share DeviceOwner permissions to other application. 项目地址: https://gitcode.com/gh_mirrors/dh/Dhizuku Dhizuku是一个创新的Android开源工具&a…

作者头像 李华
网站建设 2026/5/8 16:56:42

开发板推送代码到gitlab仓库

摘要 一次性讲透、直接能用的 git bundle create 完整用法,专门适配的场景:Jetson 板子 → 本地电脑 → GitLab, 整套固定流程:Jetson AGX 用 git bundle 打包 → 拷到本地 → 解包 → 推送到 GitLab 一、为什么要用 git bundle&a…

作者头像 李华
网站建设 2026/5/8 16:55:21

终极解决方案:Blender与Rhino的3D数据无缝迁移革命

终极解决方案:Blender与Rhino的3D数据无缝迁移革命 【免费下载链接】import_3dm Blender importer script for Rhinoceros 3D files 项目地址: https://gitcode.com/gh_mirrors/im/import_3dm 当建筑设计师精心构建的曲面模型在导入Blender后出现诡异变形&am…

作者头像 李华
网站建设 2026/5/8 16:55:08

通过 TaoToken CLI 工具一键配置多开发环境与团队协作

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过 TaoToken CLI 工具一键配置多开发环境与团队协作 在团队协作开发中,统一大模型 API 的接入配置是一个常见痛点。每…

作者头像 李华
网站建设 2026/5/8 16:54:43

网上祭祀平台哪个靠谱

网上祭祀平台哪个靠谱?我推荐“天堂念APP” 随着绿色祭祀、云端追思的理念深入人心,越来越多的人开始选择网上祭祀平台寄托哀思。但在众多平台中,如何选择一个靠谱、功能全面且服务贴心的平台?经过多方比较和实际体验&#xff0c…

作者头像 李华
网站建设 2026/5/8 16:54:42

高性能动态化客户端应用开发框架选型指南

一、背景:企业级客户端的三大核心挑战 在移动互联网时代,企业级客户端应用面临三大核心挑战: 挑战 说明 多端覆盖 需同时支持 Android、iOS、HarmonyOS(鸿蒙)、Web、小程序 高性能体验 用户对流畅度要求极高&…

作者头像 李华