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可以访问到&#

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

智慧环保之环境网格化监测解决方案

1. 引言 智慧环保网格化监测解决方案&#xff0c;旨在通过先进的信息技术手段&#xff0c;实现环境质量的全面、精准、实时监测&#xff0c;为环境治理提供科学依据和决策支持。 2. 背景与挑战 当前&#xff0c;环境污染问题日益严峻&#xff0c;治理难度不断加大。传统监测手…

vue2+3 —— Day5/6

自定义指令 自定义指令 需求&#xff1a;当页面加载时&#xff0c;让元素获取焦点&#xff08;一进页面&#xff0c;输入框就获取焦点&#xff09; 常规操作&#xff1a;操作dom “dom元素.focus()” 获取dom元素还要用ref 和 $refs <input ref"inp" type&quo…

2024 RISC-V 中国峰会 演讲幻灯片和视频回放 均已公开

目录 一、幻灯片地址&#xff1a; 二、演讲视频&#xff1a; 一、幻灯片地址&#xff1a; RVSC2024/slides at main cnrv/RVSC2024 GitHub 二、演讲视频&#xff1a; RISC-V国际基金会的个人空间-RISC-V国际基金会个人主页-哔哩哔哩视频 参考&#xff1a; 1、RISC-V 中…

sudu问题 --> 添加用户到系统配置文件里面

我们重新创建一个用户lisi 密码&#xff1a;lisixxxxxxxx 重新连接&#xff0c;输入用户&#xff0c;输入密码 是不行的 我们输入exit退出 打开文件 再切换身份&#xff0c;切换为超级管理员root 输入密码 再打开 我们打开后设置行号在50行左右可以看到我们的目标 我们再进行…

C++: string(二)

✨✨ 欢迎大家来到我的文章✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 分类专栏&#xff1a;c 我的主页&#xff1a;tyler s blog 文章目录 一 string的成员函数1 insert2 resize3assign4erase5replace6 find(1) find(2)rfind…

【无人机设计与控制】基于MATLAB的四旋翼无人机PID双闭环控制研究

摘要 本文基于MATLAB/Simulink环境&#xff0c;对四旋翼无人机进行了PID双闭环控制设计与仿真研究。通过分析四旋翼无人机的动力学模型与运动学模型&#xff0c;建立了姿态和位置双闭环控制系统&#xff0c;以实现无人机的稳定飞行与精确轨迹跟踪。仿真实验验证了该控制策略的…

DimensionX 部署笔记

目录 生成视频用CogVideoX-5b-I2V 推理代码&#xff1a; DimensionX 生成视频用CogVideoX-5b-I2V 推理代码&#xff1a; 可以生成&#xff0c;从左向右旋转的&#xff0c;也可以生成从上往下旋转的&#xff1a; import torch from diffusers import CogVideoXImageToVideo…

如何利用SAP低代码平台快速构建企业级应用?

SAP作为全球领先的企业管理软件解决方案提供商&#xff0c;一直致力于为企业提供全面且高效的业务管理工具。随着技术的快速发展&#xff0c;传统的开发方式已经无法满足企业在快速变化的市场环境下的需求。低代码开发平台应运而生&#xff0c;它通过简化应用程序的创建过程&am…

拉取docker镜像应急方法

发现许多docker hub镜像网址速度也慢得发指啦&#xff0c;如果想速度快点&#xff0c;可以考虑买个按量计费的公有云服务器&#xff0c;用他们的内网镜像&#xff0c;然后再导出&#xff0c;然后传到本地。 开通服务器 可以考虑个开通最低配的&#xff0c;这里我用的是腾讯的…

Ubuntu下的Eigen库的安装及基本使用教程

一、Eigen库介绍 简介 Eigen [1]目前最新的版本是3.4&#xff0c;除了C标准库以外&#xff0c;不需要任何其他的依赖包。Eigen使用的CMake建立配置文件和单元测试&#xff0c;并自动安装。如果使用Eigen库&#xff0c;只需包特定模块的的头文件即可。 基本功能 Eigen适用范…

Ansible一键部署Kubernetes集群

一、环境准备 主机 ip地址 角色 k8s-master 192.168.252.141 master k8s-node1 192.168.252.142 node k8s-node2 192.168.252.143 node 二、实战 Ansible部署 主节点安装Ansible yum -y install epel-release yum -y install ansible ansible --version 开启记…

Comfy UI Manager 自定义节点管理

在 Stable Diffusion Web UI 中&#xff0c;可以通过插件的方式&#xff0c;扩展更多的功能&#xff0c;如&#xff1a;tagger提示词反推、ControlNet 等。 同样的在 Comfy UI 中有类似的功能实现&#xff0c;不过在 Comfy UI 中叫做自定义节点。 通过安装自定义节点的方式&a…

第二十周:机器学习

目录 摘要 ABSTRACT 一、吴恩达机器学习exp2——逻辑回归 1、logistic函数 2、数据预处理 3、损失函数 4、梯度下降 5、设定评价指标 6、决策边界 7、正则化 二、动手深度学习pytorch——数据预处理 1、数据集读取 2、缺失值处理 3、转换为张量格式 总结 摘要…

从人-物到人-机再到人-AI

从 人-物 到 人-机 再到 人-AI &#xff0c;这一演化过程展现了人类与技术、工具的互动方式随着时代的发展而发生的深刻变化。这一变化不仅是技术进步的体现&#xff0c;更是社会、文化以及工作方式的根本转变。以下是这一演变的主要特点及其背后的影响&#xff1a; 1. 人-物时…

go-zero(三) 数据库操作

go-zero 数据库操作 在本篇文章中&#xff0c;我们将实现一个用户注册和登录的服务。我们将为此构建一个简单而高效的 API&#xff0c;包括请求参数和响应参数的定义。 一、Mysql连接 1. 创建数据库和表 在 MySQL 中创建名为 test_zero的数据库&#xff0c;并创建user 表 …

【ASR技术】WhisperX安装使用

介绍 WhisperX 是一个开源的自动语音识别&#xff08;ASR&#xff09;项目&#xff0c;由 m-bain 开发。该项目基于 OpenAI 的 Whisper 模型&#xff0c;通过引入批量推理、强制音素对齐和语音活动检测等技术。提供快速自动语音识别&#xff08;large-v2 为 70 倍实时&#xf…

【C++ 算法进阶】算法提升十六

目录 背包问题变种 &#xff08;动态规划&#xff09;题目题目分析 连续可组成数字题目题目分析 min-patches题目 最小补丁问题题目分析代码 逆序对个数 &#xff08;归并排序&#xff09;题目题目分析 约瑟夫环问题 &#xff08;公式&#xff09;题目题目分析 背包问题变种 &a…

链表的基本操作

链表&#xff0c;由若干个结点组成&#xff0c;每个结点包含数据域和指针域。结点结构如下图所示&#xff1a; 一般来讲&#xff0c;链表中只会有一个结点的指针域为空&#xff0c;该结点为尾结点&#xff0c;其他结点的指针域都会存储一个结点的内存地址。链表中也只会有一个结…

C#高级:Winform中的自定义窗体输入

目录 一、多样式输入&#xff08;无封装&#xff09; 1.代码 2.效果 二、单输入框封装 1.使用 2.封装 3.效果 三、组合框批量输入封装 1.使用 2.封装 3.效果 一、多样式输入&#xff08;无封装&#xff09; 1.代码 private async void button1_Click(object send…

memblock内存分配器

一、简述 memblock 是 Linux 内核中的一个内存管理子系统&#xff0c;主要用于在系统启动早期阶段管理物理内存。它在内核初始化期间负责管理内存&#xff0c;直到更复杂的内存管理子系统&#xff08;如伙伴系统&#xff09;接管。 二、工作原理 初始化&#xff1a;在内核启…