当前位置: 首页 > news >正文

02_Spring_IoC实现

接下来先简单说一下关于IoC的一些要点,后面我们再详细一步一步讨论。

一、IoC控制反转

  • IoC控制反转它是一种思想,不是具体的实现
  • 控制反转的目的是为了降低程序的耦合度,提高程序的可扩展性,从而满足OCP原则和DIP原则
  • 控制反转,那到底反转是什么东西?
    • 我们不再使用某个对象去直接使用代码去new了,对于这种对象的创建权利交出去了。
    • 对象与对象之间关系的维护交出去了
  • 控制反转这种思想如何实现的呢?在Spring框架当中使用DI(依赖注入)实现

二、依赖注入

依赖注入实现了控制反转思想,在Spring当中就是使用依赖注入的方式来实现对Bean的管理的。

Bean管理,是管理啥子?

既然依赖注入是实现了控制反转这种思想,那么Bean管理就是对这种思想的实际体现,所以管理的就是Bean对象的创建;Bean对象中属性的赋值(Bean对象之间的关系)。

我们来拆解一下依赖注入:

  • 依赖:对象与对象之间的关联关系
  • 注入:指的是一种数据传递的行为,通过注入这种行为来让对象与对象之间产生关系

常见的依赖注入实现方式有:set注入构造注入

set注入

新增实例来说明具体的实现

新增模块,pom文件中添加依赖

<!-- spring context -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.1.9</version>
</dependency><!--junit-->
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>

新增Dao类

public class UserDao {public void insert() {System.out.println("正在保存用户数据...");}
}

新增Service类,这里service要依赖UserDao实例对象

public class UserService {private UserDao userDao;// 使用set方式注入,必须提供set方法// 反射机制要调用这个方法为属性赋值public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save() {userDao.insert();}
}

新增Spring的配置文件spring.xml

在这个配置文件中,我们就要定义两个bean,同时要声明两个bean中的依赖关系,从下面的配置可以看到我们在声明UserService类对应的bean时,其中就使用set注入,这个与我们实际代码是对应的UserService类中有一个属性要求是UserDao类对象。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userDaoBean" class="com.xiaoxie.dao.UserDao"/><bean id="userServiceBean" class="com.xiaoxie.service.UserService"><!-- set注入 --><property name="userDao" ref="userDaoBean"/></bean></beans>

新增测试类

public class DiTest {@Testpublic void testSetDI() {ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");UserService userService = context.getBean("userServiceBean", UserService.class);userService.save();}
}

通过运行上面的测试方法可以正常通过service对象去调用到内save()方法 

其上实现的原理:

  • 在spring配置文件中,通过property标签获取到属性名:userDao
  • 通过属性名可以推断出对应的set方法:setUserDao()
  • 通过反射机制调用setUserDao()方法给对应的属性赋值
  • property标签的name属性指的就是属性名
  • property标签的ref属性就是要注入的bean对象的id,这样的话就通过ref属性来完成bean的装配

这里说的装配,相当于一个系统有多个组件,这多个组件按一定的要求和规则组装到一起的过程。

此时如果我们把UserService类中的userDao的set方法删除后,再运行测试方法,程序会报异常:Bean property 'userDao' is not writable or has an invalid setter method.

在解析配置文件推断set方法的逻辑是,通过property中的name属性的值来推断,如果值是userDao,那么推断的方式是:"set" + "userDao".substring(0,1).toupperCase() + "userDao",substring(1)   ===> setUserDao

只要在要进行依赖注入的类中存在推断出来的方法即可,它在装配时就会调用这个方法,通过这个方法来进行属性的赋值,打比方,我们把代码修改为如下:

public class UserService {private UserDao userDao;public void setAbc(UserDao userDao) {this.userDao = userDao;}public void save() {userDao.insert();}
}

那么对应的配置文件也应该同步修改为如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userDaoBean" class="com.xiaoxie.dao.UserDao"/><bean id="userServiceBean" class="com.xiaoxie.service.UserService"><!-- set注入 --><property name="abc" ref="userDaoBean"/></bean></beans>

构造注入

构造注入指的是在装配时通过构造方法来给指定的属性赋值

新增OrderDao类

public class OrderDao {public void createOrder() {System.out.println("正在创建订单...");}
}

新增OrderService类

public class OrderService {private OrderDao orderDao;public OrderService(OrderDao orderDao) {this.orderDao = orderDao;}public void create() {orderDao.createOrder();}
}

spring配置文件中进行构造方法注入的配置

<bean id="orderDaoBean" class="com.xiaoxie.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.xiaoxie.service.OrderService"><constructor-arg index="0" ref="orderDaoBean"/>
</bean>

测试类中进行测试

OrderService orderService = context.getBean("orderServiceBean", OrderService.class);
orderService.create();

对于构造方法注入,使用的标签是:<constructor-arg>

因为要注入,所以要指定哪个bean实例赋值给那个属性进行装配,这个装配的“图纸”一定要搞清楚,要不然会出错,那这里要如何对应呢?

对应关系可以通过如下几种方式来指定:

  • 通过下标来指定,比如上例中的index属性,下标是从0开始的,0表示构造方法中的第一个参数,1表示第二个参数,依次类推
  • 通过参数名称来指定,比如上列中还可以修改为<constructor-arg name="orderDao" ref="orderDaoBean"/>
  • 也可以不指定下标和参数名,比如上列中直接写为<constructor-arg ref="orderDaoBean"/> 

注意:当我们既不指定index也不提定nane时,只是指定了ref(待注入的bean)时要保证构造方法中的各个参数类型是唯一的,因为这个时候spring是根据参数的类型与指定ref的类型去匹配注入的!

在我们实际使用中set注入是比较常用的,接下来专门以set注入作为一个专题来详细聊聊依赖注入

三、详聊set注入

注入外部Bean(常用)

前面我们在举例set注入的时候就是一种外部Bean注入的方式

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="userDaoBean" class="com.xiaoxie.dao.UserDao"/><bean id="userServiceBean" class="com.xiaoxie.service.UserService"><property name="userDao" ref="userDaoBean"/></bean>
</beans>

它的特点就是,待注入的bean是定义在当前bean的外部的,在当前bean中要注入它的时候使用ref来进行注入。一般来说都是采用这种方式进行注入,单独把bean定义在外部可以提高这个bean的复用性,谁知道有没有其它的bean要注入这个bean呢?

注入内部Bean(使用少)

<!-- 使用内部bean注入 -->
<bean id="userServiceBean" class="com.xiaoxie.service.UserService"><property name="userDao"><bean class="com.xiaoxie.dao.UserDao"/></property> 
</bean>

这种方式在<property>标签内部再写一个bean标签,使用这种方式进行注入叫注入内部Bean,这个内部的bean只在这个bean可以访问到&#

相关文章:

02_Spring_IoC实现

接下来先简单说一下关于IoC的一些要点,后面我们再详细一步一步讨论。 一、IoC控制反转 IoC控制反转它是一种思想,不是具体的实现控制反转的目的是为了降低程序的耦合度,提高程序的可扩展性,从而满足OCP原则和DIP原则控制反转,那到底反转是什么东西? 我们不再使用某个对象…...

使用Python3实现Gitee码云自动化发布

仓库信息 https://gitee.com/liumou_site/ip 实现代码 import osimport requests from loguru import loggerdef gitee(ver, message, prerelease: bool False):"""在 Gitee 上创建发布版本:param ver: 版本号:param message: 发布信息:param prerelease: 是…...

Ubuntu24.04下的docker问题

按官网提示是可以安装成功的&#xff0c;但是curl无法使用https下载&#xff0c;会造成下述语句执行失败 # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https…...

PAT (Basic Level) Practice (中文)1002 写出这个数

读入一个正整数 n&#xff0c;计算其各位数字之和&#xff0c;用汉语拼音写出和的每一位数字。 #include<bits/stdc.h> using namespace std; string a; int sum0; int f0; int n[10005]; int main(){ cin>>a; int c0; int laa.size(); for(int i…...

C07.L07.STL之映射.应用2.统计数字

题目描述 某次科研调查时得到了 n 个自然数&#xff0c;每个数均不超过 1500000000 (1.5*10^9 )。已知不相同的数不超过 10000 个&#xff0c;现在需要统计这些自然数各自出现的次数&#xff0c;并按照自然数从小到大的顺序输出统计结果。 输入格式 包含 2 行&#xff1a; 第…...

微信小程序组件详解:text 和 rich-text 组件的基本用法

微信小程序组件详解:text 和 rich-text 组件的基本用法 引言 在微信小程序的开发中,文本展示是用户界面设计中不可或缺的一部分。无论是简单的文本信息,还是复杂的富文本内容,text 和 rich-text 组件都能够帮助我们实现这些需求。本文将详细介绍这两个组件的基本用法,包…...

算法.图论-习题全集(Updating)

文章目录 本节设置的意义并查集篇并查集简介以及常见技巧并查集板子(洛谷)情侣牵手问题相似的字符串组岛屿数量(并查集做法)省份数量移除最多的同行或同列石头最大的人工岛找出知晓秘密的所有专家 建图及其拓扑排序篇链式前向星建图板子课程表 本节设置的意义 主要就是为了复习…...

this.$prompt 限制输入长度

this.$prompt(请输入关键词名称, 提示, {confirmButtonText: 确定,cancelButtonText: 取消,inputPattern: /^\d{0,50}$/,inputErrorMessage: 关键词名称长度不能超过50个字符 }).then(({ value }) > {})...

JDBC使用p6spy记录实际执行SQL方法【解决SQL打印两次问题】

p6spy介绍 p6spy 是一个开源的 JDBC 数据源代理工具&#xff0c;主要用于拦截和记录应用程序与数据库之间的所有 SQL 操作&#xff0c;方便开发者进行 SQL 调试、性能监控和问题排查。 p6spy可以打印实际执行的sql&#xff0c;在开发过程中方便调试&#xff0c;和使用框架无关…...

问题: redis-高并发场景下如何保证缓存数据与数据库的最终一致性

在高并发场景下&#xff0c;Redis 通常用作缓存层&#xff0c;与数据库结合使用以提高系统的性能。为了保证缓存数据与数据库的最终一致性&#xff0c;通常采用的有双写机制、缓存失效机制&#xff0c;基于双写机制、缓存失效机制又衍生出来了消息队列、事件驱动架构等 常见机…...

Stable Diffusion核心网络结构——CLIP Text Encoder

&#x1f33a;系列文章推荐&#x1f33a; 扩散模型系列文章正在持续的更新&#xff0c;更新节奏如下&#xff0c;先更新SD模型讲解&#xff0c;再更新相关的微调方法文章&#xff0c;敬请期待&#xff01;&#xff01;&#xff01;&#xff08;本文及其之前的文章均已更新&…...

C语言-11-18笔记

1.C语言数据类型 类型存储大小值范围char1 字节-128 到 127 或 0 到 255unsigned char1 字节0 到 255signed char1 字节-128 到 127int2 或 4 字节-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647unsigned int2 或 4 字节0 到 65,535 或 0 到 4,294,967,295short2 字节…...

数据结构_图的遍历

深度优先搜索遍历 遍历思想 邻接矩阵上的遍历算法 void Map::DFSTraverse() {int i, v;for (i 0; i < MaxLen; i){visited[i] false;}for (i 0; i < Vexnum; i){// 如果顶点未访问&#xff0c;则进行深度优先搜索if (visited[i] false){DFS(i);}}cout << endl…...

设计LRU缓存

LRU缓存 LRU缓存的实现思路LRU缓存的操作C11 STL实现LRU缓存自行设计双向链表 哈希表 LRU&#xff08;Least Recently Used&#xff0c;最近最少使用&#xff09;缓存是一种常见的缓存淘汰算法&#xff0c;其基本思想是&#xff1a;当缓存空间已满时&#xff0c;移除最近最少使…...

python中的base64使用小笑话

在使用base64的时候将本地的图片转换为base64 代码如下&#xff0c;代码绝对正确 import base64 def image_to_data_uri(image_path):with open(image_path, rb) as image_file:image_data base64.b64encode(image_file.read()).decode(utf-8)file_extension image_path.sp…...

Python之time时间库

time时间库 概述获取当前时间time库datetime库区别 时间元组处理获取时间元组的各个部分时间戳和时间元组的转换 格式化时间格式化时间解析时间格式符号说明 暂停程序计时操作简单计时高精度计时计时器类的实现 UTC时间操作time库datetime库 概述 time是Python标准库中的一个模…...

Easyexcel(4-模板文件)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09; 文件导出 获取 resources 目录下的文件&#xff0c;使用 withTemplate 获…...

国产linux系统(银河麒麟,统信uos)使用 PageOffice 动态生成word文件

PageOffice 国产版 &#xff1a;支持信创系统&#xff0c;支持银河麒麟V10和统信UOS&#xff0c;支持X86&#xff08;intel、兆芯、海光等&#xff09;、ARM&#xff08;飞腾、鲲鹏、麒麟等&#xff09;、龙芯&#xff08;LoogArch&#xff09;芯片架构。 数据区域填充文本 数…...

Window11+annie 视频下载器安装

一、ffmpeg环境的配置 下载annie之前需要先配置ffmpeg视频解码器。 网址下载地址 https://ffmpeg.org/download.html1、在网址中选择window版本 2、点击后选择该版本 3、下载完成后对压缩包进行解压&#xff0c;后进行环境的配置 &#xff08;1&#xff09;压缩包解压&#…...

SAP GR(Group Reporting)配置篇(七)

1.7、合并处理的配置 1.7.1 定义方法 菜单路径 组报表的SAP S4HANA >合并处理的配置>定义方法 事务代码 SPI4...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

免费数学几何作图web平台

光锐软件免费数学工具&#xff0c;maths,数学制图&#xff0c;数学作图&#xff0c;几何作图&#xff0c;几何&#xff0c;AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...