Spring 的注入

news2025/1/12 12:07:47

目录

一、注入(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.coloradmin.cn/o/1017005.html

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

相关文章

【修复版】2023新版塔罗 算八字测运易理风水 取名 源码平台 搭建教程

全线修复&#xff0c;欢迎你拿其他家的来比&#xff0c;叫他们发测试连接去测试对比&#xff0c;眼睛骗不了人 很多说自家的是修复版&#xff0c;能像我这样把修复的列出来嘛&#xff0c;顾客朋友也可以直接去问他&#xff1a;你到底修复了个啥&#xff1f;&#xff1f;&#…

深入探索智能问答:从检索到生成的技术之旅

目录 一、智能问答概述1. **语义理解**2. **知识库和数据库**3. **上下文感知**4. **动态学习和自适应** 二、发展历程1. **基于规则的系统**2. **统计方法的兴起**3. **深度学习和神经网络的突破**4. **预训练模型** 三、智能问答系统的主要类型四、基于知识库的问答系统五、基…

如何使用记事本制作一个简陋的小网页(1)

1、创建一个记事本 2、将记事本的尾缀进行修改&#xff0c;变为html html本质上是一种标签并不是一种语言&#xff0c;其最主要的功能就是对页面设置和页面的文本样式进行修改和修缮。 3、右键被修改了尾缀的文本&#xff0c;选择使用记事本的打开方式。 打开完毕后&#xf…

什么是JavaScript的事件驱动编程(event-driven programming)?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 事件&#xff08;Event&#xff09;⭐ 事件监听器&#xff08;Event Listener&#xff09;⭐ 回调函数&#xff08;Callback Function&#xff09;⭐ 非阻塞和异步⭐ 事件循环&#xff08;Event Loop&#xff09;⭐ 触发事件&#xff08;…

「C++程序设计 (面向对象进阶)」学习笔记・二

0、引言 本专栏的系列文章是在学习 北京邮电大学 崔毅东 老师的《C程序设计 (面向对象进阶)》课程过程中整理的。欢迎前往专栏了解更多相关内容~ &#x1f600; 有关于现代 C 的基本介绍&#xff0c;请前往《现代C基本介绍》&#xff01; &#x1f514; 先决条件 本专栏的系列…

【测试开发】答疑篇 · 什么是软件测试

【测试开发】答疑篇 文章目录 【测试开发】答疑篇1. 生活中的测试2. 什么是软件测试3. 为什么要有测试/没有测试行不行4. 软件测试和软件开发的区别5. 软件测试和软件调试之间的区别6. 软件测试的岗位7. 优秀测试人员具备的素质 【测试开发】答疑篇 软件不一定是桌面应用&#…

公众号迁移线上公证如何办?

公众号账号迁移的作用是什么&#xff1f;只能变更主体吗&#xff1f;微信公众平台的帐号迁移功能可将原公众号的粉丝、文章素材、违规记录、留言功能、名称等迁移至新的公众号。通过迁移可以实现公众号的公司主体变更、粉丝转移、开通留言功能、服务号转为订阅号等作用。因此不…

Qt基于paintEvent自定义CharView

Qt基于paintEvent自定义CharView 鼠标拖动&#xff0c;缩放&#xff0c;区域缩放&#xff0c; 针对x轴&#xff0c;直接上代码 charview.h #ifndef CHARVIEW_H #define CHARVIEW_H#include <QWidget> #include <QPainter> #include <QPaintEvent> #inclu…

Kotlin使用infix关键字构建高可读性代码

自从Google推出Kotlin作为官方开发语言后&#xff0c;一堆像我这样的习惯Java开发的程序员从不习惯到爱上这门语言只用了很短的时间&#xff0c;相比于Java语言&#xff0c;kotlin集各家所长&#xff0c;可以使用更少的代码&#xff0c;实现更多更复杂的需求&#xff0c;而且可…

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

今日已办 watermill 将 key 设置到 message 中 修改 watermill-kafka 源码 将 key 设置到 message.metadata中 接入 otel-sdk 添加 middleware resolveUpstreamCtx 解析上游上下文&#xff0c;开启根Span添加 middleware middleware.InstantAck - 马上ACK&#xff0c;使得多…

怒刷LeetCode的第4天(Java版)

#【中秋征文】程序人生&#xff0c;中秋共享# 目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;遍历字符串 方法二&#xff1a;有限状态机&#xff08;Finite State Machine&#xff09; 方法三&#xff1a;正则表达式 第二题 题目来源 题目内容 解决方…

机器学习——决策树/随机森林

0、前言&#xff1a; 决策树可以做分类也可以做回归&#xff0c;决策树容易过拟合决策树算法的基本原理是依据信息学熵的概念设计的&#xff08;Logistic回归和贝叶斯是基于概率论&#xff09;&#xff0c;熵最早起源于物理学&#xff0c;在信息学当中表示不确定性的度量&…

带你了解前后端分离的秘密-Vue【vue入门】

&#x1f3c5;我是默&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Vue》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一定基础的程序员&#xff0c;这个专栏…

js中事件委托和事件绑定之间的区别

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 事件绑定&#xff08;Event Binding&#xff09;⭐事件委托&#xff08;Event Delegation&#xff09;⭐ 选择事件绑定或事件委托⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本…

NVM安装及如何使用NVM

NVM是什么&#xff1f; nvm 全名 Node Version Manager&#xff0c;Node的版本管理工具 NVM能做什么&#xff1f; 安装 nvm 后&#xff0c;可以使用nvm的相关命令来管理和切换不同的 node 版本&#xff0c;方便开发 如何安装NVM 链接: NVM GitHub地址 如何使用 NVM 命令 …

R语言绘制PCA双标图

代码&#xff1a; setwd("D:/Desktop/0000/R") #更改路径#导入数据 df <- read.table("Input data.csv", header T, sep ",")# ----------------------------------- #所需的包: packages <- c("ggplot2", "tidyr"…

1.简单工厂模式

UML类图 代码 main.cpp #include <iostream> #include "OperationFactory.h" using namespace std;int main(void) {float num1;float num2;char operate;cin >> num1 >> num2 >> operate;Operation* oper OperationFactory::createOpera…

算法综合篇专题四:前缀和

"回忆里的我&#xff0c;比国王富有。奢侈的快乐~" 1、前缀和【模板】 (1) 题目解析 (2) 算法原理 #include <iostream> using namespace std;const int N 100010; // 可能出现溢出 long long arr[N],dp[N]; int n,q;int main() {cin >> n …

长胜证券:突破五日线什么意思?

随着股市的快速开展&#xff0c;越来越多的人开端了解和参与股票投资&#xff0c;但或许会遇到一些术语和概念&#xff0c;例如“打破五日线”&#xff0c;这是新手们需求了解的。本文将介绍“打破五日线”的概念及其意义&#xff0c;同时从不同视点剖析其意义和影响因素。 什…

记录wisemodel上传失败

参考&#xff1a;https://wisemodel.cn/docs/%E6%A8%A1%E5%9E%8B%E4%B8%8A%E4%BC%A0 第一种方法&#xff1a; git lfs install git clone https://oauth2:your_git_tokenwww.wisemodel.cn/username/my_test_model.git也就是用oauth2&#xff0c;然后再按照一般的方法传文件&a…