Spring 的注入

目录

一、注入(Injection)

 1、什么是注入

(1)为什么需要注入

(2)如何进行注入

2、Spring 注入原理分析(简易版)

二、Set 注入详解

1、JDK 内置类型

(1)String + 8种基本类型

(2)数组

(3)Set 集合

(4)List 集合

(5)Map 集合

(6)properties

(7)复杂的 JDK 类型

2、用户自定义类型

第一种方式: 

第二种方式:

3、Set 注入的简化写法

(1)基于属性简化

(2)基于 p 命名空间简化

三、构造注入

1、开发步骤

2、构造方法重载

(1)参数个数不同​编辑

(2)构造参数个数相同时 

3、注入总结

四、反转控制 与 依赖注入

1、反转控制(IoC Inverse of Control)

2、依赖注入(Dependency Injection DI)


一、注入(Injection)

 1、什么是注入

所谓的注入,指的就是,通过 Spring 的工厂及配置文件为所创建对象的成员变量赋值

(1)为什么需要注入

我们原来对一个对象的变量进行赋值使用的是 get 和 set 的方法来完成的:

但是需要注意的是,此时我们所完成的赋值,是我们通过代码来完成的,并不是我们所说的注入

注入指的是通过 Spring 的配置文件对成员变量进行赋值

我们直接通过 set 来进行赋值的效果,是可以达到预期的,但是它并不好

因为它存在耦合,主要体现在

比如,日后如果这个名字不想叫馒头警告了,想叫别的名字,那么这个名字得在代码中更改,实际上这个名字在更改的过程中,就存在耦合了因为改代码涉及到重新编译,重新输出


(2)如何进行注入

1、类的成员变量提供 set,get 方法

2、 配置 Spring 的配置文件

配置文件之前,得先有对应的 get 和 set 方法!!!

此时,就完成了通过配置文件给 id 属性和 name 属性的赋值


2、Spring 注入原理分析(简易版)

 

Spring 通过底层调用对象属性对应的 set 方法来完成成员变量的赋值,这种方式我们也称之为 set 注入


二、Set 注入详解

成员变量的类型,有很多种,我们之前讲的是针对 int 和 String 类型的,所以标签使用的是 value

那如果类型变成了别的呢?比如:double ,char ,List.....

此时 <property> 里面的标签可能就要发生改变了,因为它可能是一个集合,也可能是一个数组,甚至还有可能是一个我们自己定义的类型....

针对于不同类型的成员变量,我们在 <property> 标签中,需要嵌套其它标签

<property>xxxxx
</property>

针对不同类型的成员变量,它有两种分类,一种叫做 JDK 类型的变量,也就是 java 原生的成员变量,另一种叫做 用户自定义类型 ,也就是我们自己提供的变量类型

那么接下来,我们就要针对这些不同的类型,来学习在 set 注入过程当中我们应该在 <property> 标签中嵌套什么标签来对对应的变量类型进行赋值


1、JDK 内置类型

(1)String + 8种基本类型

这里所嵌套的标签也就是我们之前所讲的 value 标签

<value>suns</value>

(2)数组

如果现在有一个 数组 类型的成员变量又该如何赋值呢?

        <property name="emails"><list><value>123456@qq.com</value></list></property>

(3)Set 集合

当变量类型为 Set 集合时:

       <property name="tels"><set><value>1381111</value><value>1391111</value><value>1661111</value></set></property>

这个时候,实际上就是为 set 集合赋值三个元素,因为 set 集合是无序的,所以我们所赋值的这三个元素,虽然我们按照顺序来进行赋值,但是未来在遍历的时候,它有可能不按照这个顺序进行注入

如果此时,这里有一个重复性的数据

比如这个手机号出现了三次,那么按照 set 集合的语义,它会帮我们把重复的数据过滤掉,最终实际上 set 集合在输出的时候,还是之前那三个元素的部分,后面重复的号码被自动过滤掉了

注意:Set 集合中的 Set 标签是固定的,但是里面嵌套的 value 标签却是不一定的

我们此时在 set 里面嵌套的是 value 标签是因为我们定义的泛型是 String ,而  String 是应该用 value,所以我们现在之所以能够嵌套 value 标签使用,原因在于 Person 当中 Set 的泛型是 String 的


(4)List 集合

当类型为 list 时:

 List 集合所使用的 list 标签和我们刚才学的数组一样,都是 list 标签

        <property name="adresses"><list><value>shengzhen</value><value>beijing</value><value>shanghai</value></list></property>

List 集合是有序的!!!

所以我们在这里按照这个顺序进行赋值,那么最后 List 集合进行遍历的时候,也一定会按照这个集合进行输出

List 集合是可以重复的!!!

所以即便有三个一样的元素,那么最后输出的时候,这三个元素都会进行输出

和 Set 集合相同的是,我们之所以能在 list 里面嵌套 value 标签,是因为此时我们的泛型是 String 类型的


(5)Map 集合

当类型是 Map 类型时:

我们之前学习 Map 的时候,就已经学习到:Map 是由键值对组成的,那么作为 map 来讲,这个键值对应该封装成一个对象,这个对象我们在之前的学习内容中就已经接触过了:Map.entry

一个 entry ,封装的就是一个键值对 

<property name="qqs"><map><entry><key><value>123</value></key><value>12415513</value></entry></map></property>

注意:此时在 key 中嵌套 value 也是因为此时的泛型是 String 类型的

同样的,因 为 值 的泛型也是 String,所以后面使用的也是 value


(6)properties

Properties类型 是一个 特殊的Map 特殊的地方在于:key=String value=String
        <property name="p"><props><prop key="key1">value1</prop><prop key="key2">value2</prop></props></property>

 这里的每一个 prop 都对应了一个键值对


(7)复杂的 JDK 类型

需要程序员自定义类型转换器,进行处理


2、用户自定义类型

第一种方式: 

1、为成员变量提供 set ,get 方法

2、 在配置文件中进行注入(赋值)   

     <bean id="userService" class="UserServiceImpl"><property name="userDAO"><bean class="UserDAOImpl"/></property></bean>


第二种方式:

第一种方式存在的一些问题:

1、配置文件代码冗余

2、被注入的对象(userDAO)被多次创建,浪费(JVM)内存资源

第二种方式的步骤与之前一样:

1、为成员变量提供 get ,set 方法

2、配置文件中进行配置(这里有区别)

先创建 userDAO 对象,再来创建 userService 对象,然后<ref bean 引用 userDAO 对象

<bean id="userDAO" class="xxx.UserDAOImpl"/></bean><bean id="userService" class="xxx.UserServiceImpl"><property name="userDAO"><ref bean="userDAO"/></property> 
</bean><bean id="orderService" class="xxx.OrderServiceImpl"><property name="userDAO"><ref bean="userDAO"/></property> 
</bean>#Spring4.x 废除了 <ref local=""/> 基本等效 <ref bean=""/>

userDAO 被多个引用,解决了代码冗余的问题,同时自始至终只用了一个 bean 标签,创建了一个 DAO 对象,也解决了内存资源浪费的问题


3、Set 注入的简化写法

(1)基于属性简化

JDK类型注⼊
<property name="name"><value>suns</value>
</property>
<property name="name" value="suns"/>注意:value属性 只能简化 8种基本类型+String 注⼊标签⽤户⾃定义类型
<property name="userDAO"><ref bean="userDAO"/>
</property>
<property name="userDAO" ref="userDAO"/>

(2)基于 p 命名空间简化 

JDK类型注⼊
<bean id="person" class="xxxx.Person"><property name="name"><value>suns</value></property>
</bean><bean id="person" class="xxx.Person" p:name="suns"/>注意:value属性 只能简化 8种基本类型+String 注⼊标签⽤户⾃定义类型
<bean id="userService" class="xx.UserServiceImpl"><property name="userDAO"><ref bean="userDAO"/></property>
</bean><bean id="userService" class="xxx.UserServiceImpl" p:userDAO-ref="userDAO"/>

三、构造注入

注入:通过 Spring 的配置文件为成员变量赋值

Set 注入:Spring 调用 Set 方法,通过配置文件为成员变量赋值

构造注入:Spring 调用构造方法,为成员变量赋值

1、开发步骤

(1)提供有参构造方法

因为我们得通过有参的构造方法来为对应的成员变量进行赋值

(2)提供Spring 的配置文件进行配置

一个 <constructor-arg> 标签,对应一个构造方法中的构造参数,个数以及顺序和构造参数的顺序是一样的


2、构造方法重载

 当构造方法发生了重载之后,我们要如何进行注入呢?

构造方法重载:方法名一样,但是参数表不                                                                              同

而所谓的参数表不同指的是参数的类型不同,参数的个数不同,参数的顺序不同,那么一旦构造方法发生重载,我们在注入的时候又要注意哪些细节呢?

(1)参数个数不同

通过控制 <constructor-arg> 标签的数量来进行区分 

    <bean id="customer2" class = "Constructor.customer"><constructor-arg><value>xiaohei</value></constructor-arg></bean>

(2)构造参数个数相同时 

然后,我们再对 age 进行实验:

    <bean id="customer" class = "Constructor.Customer"><constructor-arg><value>18</value></constructor-arg></bean>

此时就发现了一个问题:这个 18 并没有给 age 赋值,而是给 name 赋值了

这是因为 Spring 优先选择了上面的构造方法进行使用

那么如何解决这个方法呢?

name 和 age 最大的区别就是类型不同,所以这个时候我们要额外进行一个限定:指定类型

在  <constructor-arg> 后面新增一个属性,叫做 type

此时就能解决问题了


3、注入总结

在未来写项目的时候,是使用 Set 注入更多还是 构造注入 更多呢?

使用 Set 注入更多

1、构造注入比较麻烦(存在重载的问题)

2、Spring 框架底层,大量应用了 set 注入

综上,在未来,set 注入使用的更多


四、反转控制 与 依赖注入

1、反转控制(IoC Inverse of Control)

控制:对于成员变量赋值的控制权

反转控制:把对于成员变量赋值的控制权,从代码中转移到 Spring 的工厂和配置文件中完成

优点:解耦合

底层实现:工厂设计模式


2、依赖注入(Dependency Injection DI)

注入:通过 Spring 的工厂及配置文件为对象(Bean / 组件)的成员变量赋值

依赖:当一个类需要另一个类的时候,就意味着依赖,一旦出现依赖,就可以把另一个类作为本类的成员变量,最终通过 Spring 进行注入(赋值)

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

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

相关文章

CountDownLatch 使用例子和代码流程

目录 CountDownLatch意思理解普通多线程运行Thread.join()实现CountDownLatch实现CountDownLatch流程new CountDownLatch(3)countDown 方法await方法 CountDownLatch意思理解 单词1: countdown 常见释义: 英[ˈkaʊntdaʊn] 美[ˈkaʊntdaʊn] n. 倒数读秒&#xff0c;倒计时(…

推荐一个高质量专栏:「前端面试必备」

文章目录 专栏作者介绍专栏介绍目录&#xff08;前25篇&#xff09;目录&#xff08;后25篇&#xff09;专栏文章部分摘抄JavaScriptVue网络请求和HTTPNode.jswebpackBabelVite微信小程序Vuexuni-appGitECharts前端工程化 写在结尾 专栏作者介绍 &#x1f90d; 前端开发工程师&…

Vulnhub系列靶机---Deathnote: 1死亡笔记

文章目录 信息收集主机发现端口扫描目录扫描dirsearchgobusterdirb扫描 漏洞利用wpscan扫描Hydra爆破 总结 靶机文档&#xff1a;Deathnote: 1 下载地址&#xff1a;Download (Mirror) 难易程度&#xff1a;so Easy 信息收集 主机发现 端口扫描 访问靶机的80端口&#xff0c;报…

Truenas scale 配置 TrueChart zerotier

起源 Official zerotier 总是在系统重启或者服务重启后&#xff0c;会丢失之前配置的IP等信息&#xff0c;使用&#xff0c;转投 TrueChart zerotier 步骤 TrueChart 官方步骤&#xff0c;按这个配置完还是不能使用&#xff0c;需要后续设置。 添加TrueChart步骤到应用库的步…

React TypeScript 定义组件的各种方式

目录 举例说明1. 使用 class 定义2. 使用函数定义2.1 使用普通函数2.2 使用函数组件 举例说明 比如我们要定义一个计数器 Counter&#xff0c;它包含一个 label 和一个 button&#xff0c;计数器的初始值由外部传入&#xff0c;点击 button 计数加 1: 这虽然是个简单组件&…

Python新手入门

文章目录 概要python代码运行结果小结 概要 以下内容为python各种输出语句的语法&#xff01; python代码 # 标准化输出 print("这是标准化输出&#xff01;")# 格式化输出 print("这是第1种%s"%"格式化输出&#xff01;") print("这是第…

智能家居产品公司网站源码,自适应布局设计,带完整演示数据

适合各类智能家居电子产品使用的网站源码&#xff0c;深色大气设计&#xff0c;自适应布局设计&#xff0c;pc手机均可完美适配&#xff0c;带完整演示数据。 独家原创资源。源码是asp开发的&#xff0c;数据库是access&#xff0c;主流的虚拟主机空间都支持asp&#xff0c;直…

冒泡排序及其优化

前言 本文将简单介绍冒泡排序及其优化版本&#xff0c;默认从小到大顺序 什么是冒泡排序 冒泡排序是一种简单且经典的排序算法。 基本思想&#xff1a; 是通过反复交换相邻的未按顺序排列的元素&#xff0c;将最小&#xff08;或最大&#xff09;的元素逐渐“浮”到正确位置…

vscode 下载安装

vscode 下载安装常用插件 vscode 官网&#xff1a; https://code.visualstudio.com/ 点击右上角 Download 进入下载选择页面 选择自己使用操作对应 CPU 架构 下载 本文使用 x86 架构 64位 windows 系统为例 跳转下载页面 自动 开始下载 下载不开始&#xff1f;试试这个直…

lighttpd以及socket和WebSocket编程

综述 本文涉及到下图绿色背景部分的内容&#xff1a; 左侧位于Linux下&#xff0c;其中包括lighttpd和socket程序&#xff1b;右侧是WebSocket程序。两者通过网络交互。 本文介绍lighttpd的基本使用方式&#xff0c;并通过编程完成一个socket服务器与浏览器端的WebSocket客户…

Spring Boot @Value读不到Nacos配置中心的值。(properties配置文件)

读不到配置中心的值&#xff0c; 配置中心的配置文件名字&#xff08;Data ID的值&#xff09;要以.properties结尾。 如果是yaml&#xff0c;就以yaml命名。

Git:Git的一些基本操作

文章目录 基本认识使用方法创建本地仓库配置本地仓库 工作区、暂存区、版本库的概念添加文件版本回退撤销修改删除操作 基本认识 首先要对Git有一个基本的认知&#xff1a; Git本质上是一个版本控制器&#xff0c;可以对一个信息的多个版本进行一些控制&#xff0c;而能对版本…

腾讯mini项目-【指标监控服务重构】2023-08-16

今日已办 v1 验证 StageHandler 在处理消息时是否为单例&#xff0c;【错误尝试】 type StageHandler struct { }func (s StageHandler) Middleware1(h message.HandlerFunc) message.HandlerFunc {return func(msg *message.Message) ([]*message.Message, error) {log.Log…

mac 本地运行 http-proxy-middleware ,请求超时

const http require(http)"/customer": {target: "http://10.10.111.192:8080/",// target: "http://user.jinfu.baohan.com/",changeOrigin: true, // 是否启用跨域// 解决mac 代理超时问题headers: {Connection: "keep-alive"},// …

脚本:python绘制七夕爱心

文章目录 效果脚本Reference 效果 脚本 import random from math import sin, cos, pi, log from tkinter import *CANVAS_WIDTH 640 # 画布的宽 CANVAS_HEIGHT 640 # 画布的高 CANVAS_CENTER_X CANVAS_WIDTH / 2 # 画布中心的X轴坐标 CANVAS_CENTER_Y CANVAS_HEIGHT /…

WebGL 根据模型矩阵的逆转置矩阵计算运动物体的光照效果

目录 前言 坐标变换引起法向量变化 变化规律&#xff1a; 魔法矩阵&#xff1a;逆转置矩阵 逆转置矩阵的用法总结 Matrix4对象的 setInverseOf 、transpose 方法规范&#xff08;以完成逆转置矩阵&#xff09; 示例代码&#xff08;LightedTranslatedRotatedCube.js&am…

前端JavaScript入门到精通,javascript核心进阶ES6语法、API、js高级等基础知识和实战 —— JS基础(二)

人生是旷野&#xff0c;不是轨道。 思维导图 一、运算符 1.1 赋值运算符 1.2 一元运算符 1.3 比较运算符 1.4 逻辑运算符 逻辑与&#xff0c;一假则假 逻辑或&#xff0c;一真则真 <!DOCTYPE html> <html lang"en"><head><meta charset&quo…

win10远程桌面控制Ubuntu服务器 - 内网穿透实现公网远程

文章目录 前言视频教程1. ubuntu安装XRDP2.局域网测试连接3. Ubuntu安装cpolar内网穿透4.cpolar公网地址测试访问5.固定域名公网地址 转载自cpolar极点云文章&#xff1a;树莓派使用Nginx 搭建轻量级网站远程访问 前言 XRDP是一种开源工具&#xff0c;它允许用户通过Windows R…

【力扣周赛】第 362 场周赛(⭐差分匹配状态压缩DP矩阵快速幂优化DPKMP)

文章目录 竞赛链接Q1&#xff1a;2848. 与车相交的点解法1——排序后枚举解法2——差分数组⭐差分数组相关题目列表&#x1f4d5;1094. 拼车1109. 航班预订统计2381. 字母移位 II2406. 将区间分为最少组数解法1——排序贪心优先队列解法2——差分数组 2772. 使数组中的所有元素…

Java 高频疑难问题系列一

​​​​​​​ 目录 ​编辑​​​​​​​ 1.零长度 2.redis的有序集的排序 3.Unsafe类 4.带资源的try语句 5.Spring如何实现计划任务 6.Java中普通代码块,构造代码块,静态代码块执行顺序 7.MyBatis缓存机制 8.Redis Java 2种类型操作转换 9.CAS底层原理和问题 1…