Spring(5)——IoC DI

devtools/2025/3/18 4:42:35/
webkit-tap-highlight-color: rgba(0, 0, 0, 0);">

初步理解IoC & DI

什么是Spring?

用一句话概括就是:Spring是包含了众多工具方法的IoC容器

那么问题又来了,什么是容器?什么是IoC容器?

1.0 什么是容器

容器是⽤来容纳某种物品的(基本)装置。⸺来自:百度百科

在开发中: List/Map是数据存储容器,Tomcat是Web容器。

1.1 什么是IoC

在早期的开发中和对于初学者的学习过程中,整个项目中对象的数量不多,对象的属性不多,对象之间的依赖不强。

在这里插入图片描述

但是随着技术的发展,一个项目中对象数量越来越多,属性越来越多,对象之间的依赖也越来越复杂。甚至于多个对象构成一个组件,组件之间的依赖也很复杂。

在这里插入图片描述

此时我们就需要一个平台,平台负责对象的生成和装配。

在这里插入图片描述

作为开发者我们只需要将对象的生产方法告诉平台,即更多的关注功能的实现。

而这个平台就是Spring的IoC容器,平台所提供的装配好依赖关系的对象,在Spring中叫做Bean

再通过一个场景去理解:在一个项目中两个服务都需要连接数据库,我们需要分别创建连接数据库的对象,同时还需要创建一些依赖对象,但是有了IoC容器后,容器会创建好一个连接对象,当我们的服务中需要数据库连接对象的时候,只需要进行相应注解的标注,容器就会自动将这个依赖对象注入。

IoC是Spring的核⼼思想,本质是 “将程序的控制权交给框架”,开发者不再需要手动管理对象和依赖,而是由容器统一调度。

IoC:Inversion of Control(控制反转),也就是说Spring是⼀个"控制反转"的容器。

这个反转主要体现在以下几个方面:

  1. 对象创建权的反转
  • 传统方式:开发者需要手动通过 new 关键字创建对象,并显式管理对象之间的依赖关系(例如通过构造函数或 setter 方法传递依赖)。

    java">// 传统方式:开发者手动创建对象和依赖
    UserService userService = new UserService();
    UserDao userDao = new UserDao();
    userService.setUserDao(userDao);
    
  • IoC 方式:对象的创建、依赖注入、生命周期管理均由容器(如 Spring)负责。开发者只需通过配置(XML/注解)或代码定义对象的依赖关系,容器会自动完成对象的实例化和依赖装配。

    java">// Spring IoC:容器自动注入依赖
    @Service
    public class UserService {@Autowired  // 容器自动注入 UserDaoprivate UserDao userDao;
    }
    

    其实IoC我们在前⾯已经使⽤了,我们在前⾯讲到,在类上⾯添加 @RestController @Controller 注解,就是把这个对象的创建方法交给Spring管理,Spring框架启动时就会加载该类,在容器中创建该类的对象。把对象交给Spring管理,就是IoC思想。

  1. 依赖管理权的反转
  • 传统方式:对象需要主动获取依赖(例如从工厂类或全局单例中获取),导致代码与具体实现强耦合。

    java">// 传统方式:对象主动获取依赖(紧耦合)
    public class UserService {private UserDao userDao = DaoFactory.getUserDao();
    }
    
  • IoC 方式:依赖由容器主动“注入”到对象中,对象是被动接受依赖。这种方式解耦了对象和依赖的具体实现,依赖关系由外部(容器)定义。

    java">// Spring IoC:依赖由容器注入(松耦合)
    public class UserService {private UserDao userDao;  // 依赖由容器注入
    }
    
  1. 控制流的反转
  • 传统程序:代码逻辑由开发者编写的代码直接控制,主流程由开发者显式调用。

    java">public static void main(String[] args) {UserService userService = new UserService();userService.doSomething();
    }
    
  • IoC 程序:程序的主流程由框架(如 Spring)控制,开发者只需通过配置或注解定义组件,框架负责调度和执行。

    java">@SpringBootApplication
    public class MyApp {public static void main(String[] args) {SpringApplication.run(MyApp.class, args); // 控制权交给 Spring}
    }
    

可以理解为传统程序中,开发者要显式的点击开始,然后程序就开始按照提前写好的顺序去执行了,在IoC程序中,点击开始,程序不会按照某个顺序去执行,流程由框架驱动,开发者只需定义组件和处理逻辑,框架决定何时调用它们。

关键总结

  • 反转的核心:将对象的创建、依赖管理、程序流程的控制权从开发者手中转移到容器或框架。
  • 解决的问题:解耦组件之间的依赖关系,使代码更灵活、可维护性更高(例如通过依赖注入实现面向接口编程)。
  • 实际体现:开发者不再需要编写 new、不再需要手动管理依赖关系、不再需要控制程序的主流程。

通过 IoC,开发者可以更专注于业务逻辑的实现,而非底层对象的创建和管理。

1.2 什么是DI

在 Spring 框架中,依赖注入(Dependency Injection) 是实现控制反转(IoC)的核心技术,它通过容器自动管理对象之间的依赖关系。

下面通过一个小案例来理解依赖注入。

这是原本的代码:

java">//用来提供数据
public class BookDao {public List<BookInfo> mockData() {List<BookInfo> books = new ArrayList<>();for (int i = 0; i < 5; i++) {BookInfo book = new BookInfo();book.setId(i);book.setBookName("书籍" + i);book.setAuthor("作者" + i);book.setCount(i * 5 + 3);book.setPrice(new BigDecimal(new Random().nextInt(100)));book.setPublish("出版社" + i);book.setStatus(1);books.add(book);}
return books;}}
java">//使用数据
public class BookService {private BookDao bookDao = new BookDao();public List<BookInfo> getBookList() {List<BookInfo> books = bookDao.mockData();for (BookInfo book : books) {if (book.getStatus() == 1) {book.setStatusCN("可借阅");} else {book.setStatusCN("不可借阅");}}return books;}
}

可以看到在BookService中我们主动new了一个BookDao对象。这里需要介绍两个注解

@Component & @Autowired

1. @Component:标记类为 Spring Bean

  • 作用:告诉 Spring 容器,“这个类需要被管理,请把它创建成一个 Bean”。
  • 使用场景:标记任意需要被 Spring 管理的类(如工具类、服务类、数据访问类)。

2. @Autowired:自动注入依赖

  • 作用:告诉 Spring 容器,“请把匹配的 Bean 自动注入到这个字段/构造器/方法中”。
  • 使用场景:在需要依赖其他 Bean 的地方(如 Service 依赖 DAO)。

将这两个注解运用到上面的案例中:

java">//告诉 Spring 容器,“这个类需要被管理,请把它创建成一个 Bean”。
@Component
public class BookService {//告诉 Spring 容器,“请把匹配的 Bean 自动注入到这个字段/构造器/方法中”。@Autowiredprivate BookDao bookDao;public List<BookInfo> getList(){List<BookInfo> books = bookDao.mockData();//处理⻚⾯展⽰for (BookInfo book:books){if (book.getStatus()==1){book.setStatusCN("可借阅");}else {book.setStatusCN("不可借阅");}}return books;}
}
java">//告诉 Spring 容器,“这个类需要被管理,请把它创建成一个 Bean”。
@Component
public class BookDao {public List<BookInfo> mockData() {List<BookInfo> books = new ArrayList<>();for (int i = 0; i < 5; i++) {BookInfo book = new BookInfo();book.setId(i);book.setBookName("书籍" + i);book.setAuthor("作者" + i);book.setCount(i * 5 + 3);book.setPrice(new BigDecimal(new Random().nextInt(100)));book.setPublish("出版社" + i);book.setStatus(1);books.add(book);}return books;}
}

先给类做**@Component**注解告诉Spring这两个类需要被管理,把他们创建成Bean,然后在BookService中需要new BooKDao()的地方做

@Autowired注解。做了这两步之后,每当需要BookService的getList()服务的时候,Spring会自动把BookDao的Bean注入到@Autowired标记过的地方。

上面这个过程就体现了依赖注入(Dependency Injection)

1.3 Bean的声明

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

在这里插入图片描述

1.4 Bean的注入

当一个Bean有多个实现类的时候,并且他们都有@Component或者其衍生注解的时候,Spring就不知道注入哪个了。

此时有三个注解可以用来解决这个问题:

  1. **@Primary:**当一个类标记了@Component或者其衍生注解的类添加@Primary注解的时候,Spring在注入Bean时会优先注入该类实现的Bean。
    在这里插入图片描述

  2. @Qualifier: 使用该注解配合@Autowired,可以指定当前注入哪个Bean。
    在这里插入图片描述

  3. **@Resource:**直接使用该注解标记注入处,不使用@Autowired。

在这里插入图片描述

@Resource与@Autowired的区别:

  1. @Autowired默认按照类型进行注入,而@Resource按照名称进行注入。
  2. @Autowired是Spring框架提供的注解,而@Resource是JDK提供的注解。

http://www.ppmy.cn/devtools/167989.html

相关文章

Spring Cloud Stream - 构建高可靠消息驱动与事件溯源架构

一、引言 在分布式系统中&#xff0c;传统的 REST 调用模式往往导致耦合&#xff0c;难以满足高并发和异步解耦的需求。消息驱动架构&#xff08;EDA, Event-Driven Architecture&#xff09;通过异步通信、事件溯源等模式&#xff0c;提高了系统的扩展性与可观测性。 作为 S…

本地部署Deep Seek-R1,搭建个人知识库——笔记

目录 一、本地部署 DeepSeek - R1 1&#xff1a;安装Ollama 2&#xff1a;部署DeepSeek - R1模型 3&#xff1a;安装Cherry Studio 二、构建私有知识库 一、本地部署 DeepSeek - R1 1&#xff1a;安装Ollama 1.打开Ollama下载安装 未科学上网&#xff0c;I 先打开迅雷再下…

【大模型技术】怎么用agent和prompt工程实现用户的要求?

使用 Agent 和 Prompt 工程 是实现用户需求的一种强大方法&#xff0c;尤其是在基于大语言模型&#xff08;LLM&#xff09;的应用中。以下是一个详细的步骤指南&#xff0c;帮助您理解如何结合 Agent 和 Prompt 工程来满足用户的需求。 一、背景知识 1. 什么是 Agent&#x…

IDE 使用技巧与插件推荐:全面提升开发效率

在软件开发领域&#xff0c;集成开发环境&#xff08;IDE&#xff09;已成为开发者不可或缺的工具。它集代码编辑、编译、调试、版本控制等多种功能于一身&#xff0c;极大地提升了开发效率。然而&#xff0c;许多开发者可能并未充分挖掘 IDE 的潜力。通过掌握一些实用的使用技…

PostgreSQL 日常SQL语句查询记录--空间查询

具体查询示例如下&#xff1a; 在pg数据库中&#xff0c;如果需要使用空间查询&#xff0c;需要先进行安装空间扩展&#xff1b; CREATE EXTENSION POSTGIS; CREATE EXTENSION PGROUTING; CREATE EXTENSION POSTGIS_TOPOLOGY; CREATE EXTENSION FUZZYSTRMATCH; CREATE EXTENSI…

uniapp上传文件问题以及返回上一页出现退出app的问题记录

uniapp上传文件使用uni.uploadFile&#xff0c;如果直接一次性在success里完成会导致页面自动刷新&#xff0c;特别是添加了本页面有onshow()方法&#xff0c;上传完会自动调用onshow()方法。 建议使用官方的方式分成两个方法处理&#xff1a; async afterRead(event) {let f…

ETIMEDOUT 网络超时问题

根据日志显示&#xff0c;你遇到的 ​**ETIMEDOUT 网络超时问题** 是由于 npm 无法连接到企业内部的 Nexus 仓库&#xff08;http://192.168.55.12:8001&#xff09;导致的。以下是具体原因和解决方案&#xff1a; 一、问题根源 ​Nexus 仓库不可达 日志中所有依赖包均尝试从 h…

CentOS 7系统初始化及虚拟化环境搭建手册

引言 随着信息技术的快速发展&#xff0c;企业对稳定、高效的操作系统环境有着更高的要求。CentOS&#xff08;Community ENTerprise Operating System&#xff09;作为一款基于Red Hat Enterprise Linux&#xff08;RHEL&#xff09;的企业级发行版&#xff0c;因其稳定性、可…