告别依赖混乱:Spring IoC 容器与 DI 依赖注入入门精讲

目录

什么是 IoC

IoC 介绍

传统开发思路

解决方法

IoC 优势

DI

IoC & DI 使用

IoC 详解

Bean 的存储

@Controller(控制器存储)

获取 bean 对象的其他方法

bean 命名

面试题之 ApplicationContext  pk BeanFactory

@Service(服务存储)

@Respository(仓库存储)

@Component(组件存储)

@Configuration(配置存储)

为什么这么多类注解?

方法注解 @Bean

定义多个对象

扫描路径

DI 详解

属性注入(Field Injection)

构造方法注入(Constructor Injection)

Setter 注入(Setter Injection)

三种注入方式的优缺点

@Autowired 存在的问题

使用@Primary:

 @Qualifier 注解:

@Resource 注解:

面试题之 @Autowird 与 @Resource 的区别

Spring,Spring Boot ,Spring MVC

完!


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

List/Map -> 数据存储容器

Tomcat -> Web 容器

什么是 IoC

我们在前面已经使用过 IoC 了,在类上面添加 @RestController 和 @Controller 注解,就是把这个对象交给 Spring 管理,Spring 框架启动的时候,就会加载该类,把对西昂交给 Spring 管理,就是 IoC 思想。

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

控制反转什么呢??? 获得依赖对象的过程被反转了。也就是说,当需要某个对象的时候,传统开发中,需要我们自己 new 一个对象,现在不需要再进行创建了,把创建对象的任务交给了容器。我们在程序中,只需要进行依赖注入即可~~ 这个容器,就称为 IoC 容器,所以有时 Spring 也被称为 Spring 容器。

IoC 介绍

我们以一个具体案例来了解 IoC 思想。

当我们需要造一辆车的时候。

传统开发思路

先设计轮子,然后根据轮子的大小设计底盘,再根据底盘设计车身,再根据车身,对整个汽车进行设计。这样一层一层设计,就会出现一个依赖关系 ,即汽车依赖车身,车身依赖底盘,底盘依赖轮子。

上面的设计的可维护性非常低。当我们的需求发生一些变化的时候,随着对车的需求量越来越大,个性化需求也会越来越多,需要加工更多尺寸的轮胎,就需要对程序进行修改了。

即问题是:当最底层的代码发生改动之后,调用链上的所有代码,都需要进行修改。程序的耦合度极高,修改一处代码,会影响其他处的代码~~

解决方法

上面程序中,我们根据轮子的尺寸设计底盘,轮子尺寸修改,底盘就需要修改,同样的,后面的车身,汽车都需要修改。

我们可以先设计汽车的大概样子,然后根据汽车来设计车身,根据车身设计底盘,根据底盘设计轮子。

我们可以尝试,不在每个类中创建自己的下积累,如果自己创建下级类,当下级类发生改变操作的时候,我们自己也要跟着修改。

改用传递(注入)的方式。

IoC 优势

传统代码中创建对象的顺序是:Car->Framework->Bottom->Tire

改进解耦合之后的顺序是:Tire->Bottom->Framework->Car

改进之后,创建对象的控制权发生了反转,不再是使用方来进行对象创建并且控制依赖对象了,而是把依赖对象注入到当前对象中,依赖对象的控制权不再由当前类进行控制了。

这部分代码,就算 IoC 容器所作的工作。

IoC 容器可进行资源的几种管理,实现资源的可配置和易管理,当我们需要使用的时候,只需要从容器中取就可以了

IoC 容器也降低了使用资源双方的依赖程度,创建实例的时候并不需要了解细节,实现了解耦合~~

DI

DI:Dependency Injection (依赖注入)

容器在运行期间,动态的为应用程序提供运行时所依赖的资源。依赖注入是从应用程序的角度进行描述,指通过引入 IoC 容器,利用依赖关系注入的方式,实现对象之间的解耦合

IoC & DI 使用

Spring 是一个 IoC 容器,管理的主要是对象,这些对象,我们称之为 Bean。Spring 来负责这些对象的创建和销毁,我们程序只需要告诉 Spring,那些需要存,以及如何从 Spring 中取出对象。

实现:

1. 把 BookDao 交给 Spring 管理,在 BookDao 类前添加 @Component 注解

2. 把 BookService 交给 Spring 管理,由 Spring 来管理对象

3. 删除 BookService 中创建 BookDao 的代码,从 Spring 中获取对象,添加 @Autowired 注解

4. 删除 BookController 中创建 BookService 的代码,从 Spring 中获取对象,添加 @Autowried 注解

IoC 详解

系统的学习 Spring IoC 和 DI 操作。前面提到的 IoC 控制反转,就是将对象的控制权交给 Spring 的 IoC 容器,由它对对象进行创建和管理。

也就是 bean 的存储。

Bean 的存储

之前的案例中,我们要把对象交给 IoC 容器管理,需要在类上添加一个注解:@Component 

Spring 框架中,提供了更丰富的注解。

@Controller(控制器存储)

从 Spring 容器中获取对象

补充:因为我们的对象通过 @Controller 注解都交给 Spring 管理了,所以获取对象要通过 Spring 获取,那么就需要先得到 Spring 的上下文,即 ApplicationContext 翻译就是 Spring 上下文~

此时,如果我们把 @Controller 删掉,运行结果如下:

表明在 Spring 中找不到指定类型的 Bean

获取 bean 对象的其他方法

通常使用 1 2 4 三种方式获取 bean,且获取到的 bean 都是一致的

其中 1 2 都涉及到根据名称来获取对象,再来研究一下 bean 命名约定~

bean 命名

官方文档中写道:程序开发人员并不需要为 bean 指定名称,如果没有显示的提供名称,Spring 容器会为该 bean 生成唯一的名称。

命名约定就使用 Java 标准约定作为实例字段名。即,bean 名称以小写字母开头,然后使用驼峰式大小写~

也有特殊情况,即,当由多个字符,且第一个和第二个字符都是大写的时候,将会保留原始的大小写~

我们根据规则,再来进行 bean 的获取:

三条 sout 语句的结果一致

地址一样,说明对象是同一个~

面试题之 ApplicationContext  pk BeanFactory

继承关系和功能方面:Spring 容器的两个顶级的接口:BeanFactory 和 ApplicationContext。其中,BeanFactory 提供了基础的访问容器的能力,ApplicationContext 属于 BeanFactory 的子类,出了继承了 BeanFactory 的功能之外,还有了其他方面的特性~

性能方面:BeanFactory 是懒加载,用到那个加载那个。ApplicationContext 是一次性加载并初始化所有的 Bean 对象~

@Service(服务存储)

去掉 @service 注解后,仍然报错:

@Respository(仓库存储)

@Component(组件存储)

@Configuration(配置存储)

为什么这么多类注解?

@Controller:控制层,接收请求,对请求进行处理,并进行响应。

@Service:业务逻辑层,处理具体的业务逻辑。

@Respository:数据访问层,负责数据访问操作

@Configuration:配置层,处理项目中的一些配置信息

当我们对五大类注解的源码进行观察后

除 @component 之外,剩下四个注解的源码中均有 @Component 注解。说明他们本身都是属于 @Component 的子类,@Component 是一个元注解,可以对其他注解进行注解~~

剩下四个注解,可以被称为 @Component 的衍生注解~~

其实从功能上来说,五大注解大差不多可以混用,但是在逻辑上是不可以的~~

方法注解 @Bean

类注解是添加到某个类上的,但有两个问题:

        1. 使用外部包中的类,没办法添加类注解

        2. 一个类,需要多个对象,多个数据源~

这种情况,我们需要使用 @Bean 注解

 

结果如下:

方法注解是要配合类注解进行使用的。

在 Spring 框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到 Spring 容器中

定义多个对象

即,多数据源的情况,类是同一个,但配置不同,指向不同的数据源

此时,我们根据类型获取对象:

运行结果:

期望是获取到唯一一个匹配,结果发现了两个 user1 和 user2

从报错信息来分析,@Bean 注解的 bean,其名称就是它的方法名。

根据名称来获取 bean 对象:

此时可以成功获取到~

也可以对 bean 的名称进行重命名

扫描路径

Q:使用前面我们提到的四个注解生命的 bean,一定会生效吗?

A:不一定(bean 要想生效,还需要被 Spring 扫描到)

其他代码不懂,仅仅修改目录结构:

又会发现,找不到名称为 u1 的 bean。

使用五大注解声明的 bean,要想生效,还需要配置扫描路径,让 Spring 扫描到这些注解~

使用 @ComponentScan 来配置扫描路径

这种做法仅作了解~

那为什么前面我们并没有配置这个直接,也可以正常使用呢?

@SpringBookApplication 这个启动类声明注解中,已经包含 @ComponentScan 注解了~

会默认扫描 SpringBoot 启动类所在的包及其子包~

一般我们将启动类直接放在我们要被扫描的包的路径下即可~

DI 详解

依赖注入是一个过程,值 IoC 容器在创建 Bean 的时候,去提供运行时所依赖的资源(对象)

上面案例中,我们是使用了  @Autowired 注解,完成了依赖注入的操作。

简单来说,就是把对象取出来,放入某个类的属性中。

依赖注入,Spring 也提供了三种方式

属性注入(Field Injection)

属性注入是使用 @Autowired 实现的,将 Service 类注入到 Controller 类中

运行结果:

去掉 @Autowired 的时候,结果如下:空指针异常,找不到 userService

构造方法注入(Constructor Injection)

注:

        1. 如果只有一个构造函数的情况下,@Autowired 可以省略

        2. 如果有多个构造函数,需要指定默认的构造函数(@Autowired 指定)如果未指定,则默认使用无参的构造函数

        3. 构造函数规范:如果添加构造函数,把无参构造函数显示的进行添加~

Setter 注入(Setter Injection)

Setter 注入和属性的 Setter 方法实现类似,只不过在设置 set 方法时候,需要加上 @Autowired 注解

三种注入方式的优缺点

@Autowired 存在的问题

当同一个类中,存在多个 bean 的时候,使用 @Autowired 会存在问题

运行结果:

报错的原因是:非唯一的 Bean 对象

解决方案:

@Primary

@Qualifier

@Resource

使用@Primary

当存在多个相同类型的 Bean 注入时候,加上 @Primary 注解,来确认默认的实现~

 @Qualifier 注解

指定当前要注入的 bean 对象。在 @Qualifier 的 value 属性中,指定注入的 bean 的名称

注:Qualifier 注解不能单独使用,需要搭配 @Autowired 使用

@Resource 注解:

是按照 bean 的名称进行注入。通过 name 属性指定要注入的 bean 的名称

面试题之 @Autowird 与 @Resource 的区别

1. @Autowired 是 Spring 框架提供的注解,而 @Resource 是 jdk 提供的注解

2 @Autowired 默认是按照类型注入的,而 @Resource 是按照名称注入,相比 @Autowired 来说,@Resource 支持更多的参数设置~

Spring,Spring Boot ,Spring MVC

 

完!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/98062.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/98062.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频理解学习笔记

目录 VideoRefer VideoPrism 核心解密:通用视频编码器的力量 VideoRefer VideoRefer 是由浙江大学和阿里达摩院联合推出的视频对象感知与推理技术,增强视频大型语言模型(Video LLMs)的空间-时间理解能力。简单一点来说就是可以…

P1198题解

题目链接 开题第一件事看数据范围.这里的范围是二十万,支持O(nlogn). 这是一个RMQ问题,同时要加点,我们因此考虑ST表或者线段树.这里用线段树是核弹打蚊子,没有意义,我们因此考虑ST表.我们注意到如果加点操作需要改动ST表原来的东西ST表就会炸掉,我们就要考虑更高级的数据结构…

使用yolov8对视频进行目标检测

使用 Ultralytics 的 YOLO 模型对视频进行逐帧目标检测非常简单,以下是完整的实现方法: 我们的输入视频是这样的 视频目标检测输入视频这里是天津市和平区天津大学附近,感兴趣的小伙伴来天津玩哈!! 1. 安装依赖 确保已…

Edge浏览器的自动化点击系统

Tag_click_openclose_V6 开发与使用注意事项 网页自动化点击系统 一个基于Python和CustomTkinter开发的桌面应用程序,通过Selenium实现对Edge浏览器的自动化控制。点击Tag_click_openclose_V6进入Github自取,记得点赞收藏嗷。 功能介绍 连接到已打开…

Python股票数据分析与预测系统 LSTM神经网络算法 股票价格预测 Tensorflow深度学习 机器学习 Flask框架 东方财富(建议收藏)✅

博主介绍:✌全网粉丝50W,前互联网大厂软件研发、集结硕博英豪成立软件开发工作室,专注于计算机相关专业项目实战6年之久,累计开发项目作品上万套。凭借丰富的经验与专业实力,已帮助成千上万的学生顺利毕业,…

英莱科技焊缝跟踪系统亮相德国埃森焊接展,激光视觉点亮世界舞台

9月15-19日,每4年一届的德国埃森焊接与切割展览会(SCHWEISSEN & SCHNEIDEN)即将盛大开幕。作为焊接行业最具规模及权威性的盛会之一,英莱科技将携全新PF系列激光视觉焊缝跟踪系统惊艳亮相,为全球智能化焊接贡献中国…

嵌入式基本概念:什么是指令集,微架构,IDE,DFP等等是什么意思,有什么关系???

注:下面是指令集和微框架的分类图,后面我会以ARM的M4举例子。 一.什么是指令集 大概的可以看这个视频 https://www.bilibili.com/video/BV1uXzbYBEy2/?spm_id_from333.1007.top_right_bar_window_custom_collection.content.click&vd_source406ed…

Spring Cloud之服务入口Gateway之自定义过滤器

目录 过滤器执行顺序 自定义过滤器 自定义GatewayFilter 定义GatewayFilter 配置过滤器 启动服务并访问 自定义GlobalFilter 定义GlobalFilter 启动服务并访问 服务部署 过滤器执行顺序 如果⼀个项⽬中, 既有GatewayFilter, ⼜有 GlobalFilter时, 执⾏的先后顺序是什…

MySQL——视图、储储过程、触发器

目录 一、视图 二、存储过程 三、触发器 一、视图 视图是一种虚拟存在的表。视图中的数据并不在数据库中真实存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。通俗的讲,视图只保存了查询的SQL逻辑&#xff0c…

iOS App 卡顿与性能瓶颈排查实战 如何定位CPU内存GPU帧率问题、优化耗电与网络延迟(uni-app开发性能优化全流程指南)

在 iOS 应用开发中,卡顿 是用户最直观的负面体验。 一个 App 如果在页面切换、滚动、后台运行时频繁掉帧或发热,用户很快就会放弃使用。 对于 uni-app 跨平台开发者 来说,卡顿问题更为复杂: JS 与原生层桥接增加了 CPU 负载&#…

腾讯开源多模态 RAG:复杂文档秒变自建知识库,支持 API 调用

上篇,分享了 小智AI MCP系列的第一篇: 小智 AI 闹钟提醒 定时任务,设备端MCP实现 有朋友问,能否接入知识库 RAG? 让小智可以根据企业知识库,回答客户的疑问~ 当然可以,接入方式同样是 MC…

Node.js中的 http 模块详解

http 模块是 Node.js 中的核心模块之一,专门用于构建基于 HTTP 的网络应用程序。它允许创建 HTTP 服务器和客户端,处理网络请求和响应。1. 核心 API 详解1.1. http.createServer([options][, requestListener])用于创建 HTTP 服务器的核心方法&#xff0…

LAMP 环境部署

LAMP 环境部署 一、概述 1. 目的 基于 CentOS 7 系统部署 LAMP(Linux Apache MySQL PHP)环境的完整步骤,通过脚本化操作实现环境快速搭建,适用于运维人员进行测试环境或基础生产环境的 LAMP 部署 2. 适用环境操作系统&#xff…

用html5仿造nes游戏敲玻璃写一个敲玻璃游戏

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>敲玻璃游戏</title><style>body {ma…

996引擎-ItemTips特效框层级自定义

996引擎-ItemTips特效框层级自定义 需求场景 ItemTips 中相关方法 创建特效的位置 创建特效框 核心修改 调整视图,自己加个背景,不用原来的 设置 tipsLayout_bg 的层级 结果预览 参考资料 需求场景 策划说我们的tips特效框,遮挡文字。如果按官方说的设为底层又跑到背景框后…

Java 注解与 APT(Annotation Processing Tool)

Java 注解与 APT&#xff08;Annotation Processing Tool&#xff09; 注解&#xff08;Annotation&#xff09;基础 注解是 Java 语言的一种元数据形式&#xff0c;它可以在代码中添加标记信息&#xff0c;用于描述代码的额外信息&#xff0c;但不会直接影响代码的执行逻辑。注…

Unity 检测网络-判断当前(Android/Windows平台)设备是否连接了指定WiFi

判断设备是否连接了特定的网络1.Unity 脚本2.Unity AndroidManifest.xml文件①改个设置②补充权限语句1.Unity 脚本 using UnityEngine; using System.Collections; using System.Diagnostics; using Debug UnityEngine.Debug; using UnityEngine.UI;#if UNITY_ANDROID &…

通过网络强化增强混合IT环境的安全

网络是企业运营的支柱&#xff0c;也是网络犯罪分子和恶意威胁者的主要目标&#xff0c;他们会破坏IT运营的连续性。随着混合云基础设施、远程办公和物联网&#xff08;IoT&#xff09;生态系统的出现&#xff0c;网络边界正在不断扩大&#xff0c;新的漏洞不断产生&#xff0c…

ACP(四):RAG工作流程及如何创建一个RAG应用

RAG的工作原理 你在考试的时候有可能会因为忘记某个概念或公式而失去分数&#xff0c;但考试如果是开卷形式&#xff0c;那么你只需要找到与考题最相关的知识点&#xff0c;并加上你的理解就可以进行回答了。 对于大模型来说也是如此&#xff0c;在训练过程中由于没有见过某个知…

宇视设备视频平台EasyCVR视频设备轨迹回放平台监控摄像头故障根因剖析

监控摄像头的类型繁多&#xff0c;市场上提供了广泛的选择。然而&#xff0c;在使用监控摄像头的过程中&#xff0c;用户可能会遇到云台在很短的时间内出现运转不灵或完全无法转动的问题。这里&#xff0c;我们将对这一常见问题进行深入分析。一、具体的原因&#xff1a; 1、距…