依赖注入~
创始人
2025-05-30 19:24:35

依赖注入之setter注入:

依赖注入是IOC具体的一种实现方式, 这是针对资源获取的方式角度来说的,之前我们是被动接受,现在IOC具体的实现叫做依赖注入,从代码的角度来说,原来创建对象的时候需要new,而现在并不需要这样做,只需要将所依赖的对象给它设置相对应的方法,set方法也行,有参构造也行,以我们设置好的方法来接受spring为我们所注入的对象

比如,我们此时创建一个实体类,其中包含id,age,name等属性,那我们就说student对象是依赖于id/name/age这些属性的,既然student依赖于这些属性,那么我们就可以在IOC容器中为其进行赋值,依赖注入通俗点说就是为类中的属性赋值的过程

student类:

package xysfxy;public class student implements person {private  Integer sid;private  String sname;private  Integer age;private  String gender;public student() {}public Integer getSid() {return sid;}public void setSid(Integer sid) {this.sid = sid;}public String getSname() {return sname;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public void setSname(String sname) {this.sname = sname;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}@Overridepublic String toString() {return "studnet{" +"sid=" + sid +", sname=" + sname +", age=" + age +", gender='" + gender + '\'' +'}';}public student(Integer sid, String name, Integer age, String  gender ) {this.age=age;this.sname=sname;this.gender=gender;this.sid = sid;}
}

如下所示,当我们为student类中的name属性赋值,注意:name在这里是属性,那么什么叫属性呢?找到当前类中set和get方法,把方法中的set和get去掉,剩余部分的首字母变成小写的结果就是属性,由于我们当前是给属性赋值,因此需要寻找set方法

在这里插入图片描述
在spring.xml文件中为属性赋值:




import org.junit.Test;
import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;
import xysfxy.student;public class student_text {@Testpublic void test(){ApplicationContext ioc=new ClassPathXmlApplicationContext("applicantsContext.xml");student student= ioc.getBean(student.class);System.out.println(student);}
}

输出如下所示:

studnet{sid=1001, sname=张三, age=20, gender='男'}

此时输出的结果正是我们上述所赋的值。

依赖注入之构造器注入:

在spring.xml文件中赋值:



其他不变,运行结果如下所示:

studnet{sid=1002, sname=李四, age=19, gender='男'}

在上述student类中,添加score属性,并创建新的有参构造:

//新的有参构造中使用score属性代替age属性
public student(Integer sid, String name, String  gender , double score) {this.sid = sid;this.sname=name;this.gender=gender;this.score=score;}
//原有参构造public student(Integer sid, String name, String  gender, Integer age ) {this.sid = sid;this.sname=name;this.gender=gender;this.age=age;}//重写tostring方法@Overridepublic String toString() {return "student{" +"sid=" + sid +", sname='" + sname + '\'' +", age=" + age +", gender='" + gender + '\'' +", score=" + score +'}';}//为新添加的set和get属性设置set和get方法public double getScore() {return score;}public void setScore(double score) {this.score = score;}

spring.xml文件中的参数设置不变:


运行结果如下:

student{sid=1002, sname='李四', age=null, gender='男', score=24.0}

我们发现在当有参构造器中包含参数相同的情况下,数据24既可以匹配给整形age,也可以匹配给double类型的score, 测试结果如下:

在这里插入图片描述

我们发现默认情况下,24匹配给了score,但如果我们对上述这种情况想要把24匹配给年龄呢?

关于这种情况网上的解决方法有很多:

 方法1:spring.xml文件的bean标签的最后一个属性值设置时,指定name="age"
 方法2:将有参构造中包含age的那个构造方法放在另一个的前面

我使用第二种方式可以,但第一种就会报错,至于为什么不能两个方法通用,我也很疑惑…

依赖注入之特殊值处理:

字面量赋值:

什么是字面量?

int a=10;

声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字,当我们引用a的时候,我们实际上拿到的值是10,而如果a是带引号的:“a”,那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量,所以字面量没有引申含义,就是我们看到的这个数据本身。

举例:

我们在spring.xml文件中设置gender属性的值为"null":

 

输出如下所示:

student{sid=1002, sname='李四', age=24, gender='null', score=0.0}

我们发现,gender最终输出的值就是null,那他表示的是null对象还是值为null的字符串呢?

我们可通过下述代码进行测试,如果没有报错,则证明当前的null为值是null的字符串:

System.out.println(student.getGender().toString());

在这里插入图片描述

如果它真的是null对象的话,应该报错为空指针异常

正确的将属性设置为null对象的方法如下:



输出如下:

在这里插入图片描述

xml实体:

小于号在XML文档中用来定义标签的开始,不能随便使用,如下所示:

在这里插入图片描述

解决方案:使用XML实体来代替,如下所示:

<表示小于号,>表示大于号

 

输出结果如下所示:

此时的sname的值中的大括号和小括号都被显示出来

student{sid=1002, sname='<张三>', age=11, gender='null', score=0.0}

关于特殊符号无法被解析的问题,我们还有另外一种办法,就是使用CDATA节CDATA中的C代表Character,是文本,字符的含义,CDATA就代表纯文本数据,XML解析器看到CDATA就知道这里是纯文本,就不会当做XML标签或属性来解析,所以CDATA节中写什么都任意,在IDE中,我们可以通过快捷键使用这个功能,CD[一定要大写],回车即可,如下所示:

 ]]>

输出如下:

这种方式也可以正确的显示特殊字符,但需要注意的是它是XML中一个特殊的标签,我们不能将其当做value属性的值写在value属性的后面

student{sid=1002, sname='<张三>', age=11, gender='null', score=0.0}

依赖注入之为类类型的属性赋值:

创建实体类班级:

package poij;public class clazz {private  Integer cid;private  String name;public Integer getCid() {return cid;}public void setCid(Integer cid) {this.cid = cid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public clazz(Integer cid,String name) {this.cid = cid;this.name=name;}public clazz() {}@Overridepublic String  toString() {return "clazz{" +"cid=" + cid +", name='" + name + '\'' +'}';}
}

修改student类:

//班级和学生之间是一对多的关系,将作为属性加入到学生类中private  clazz clazz;//并为新的属性设置set和get方法public poij.clazz getClazz() {return clazz;}public void setClazz(poij.clazz clazz) {this.clazz = clazz;}//重写toString方法@Overridepublic String toString() {return "student{" +"sid=" + sid +", sname='" + sname + '\'' +", age=" + age +", gender='" + gender + '\'' +", clazz=" + clazz +'}';}

那么对于student类来说,clazz属性该如何赋值呢?

我们不能使用value对其进行赋值,因为value是给字面量赋值的,但clazz对应的是一个对象

那么该如何给类类型赋值呢?

引用外部的bean给类类型赋值:





输出如下所示:

在这里插入图片描述

通过级联方式给类类型赋值:

在mybatis中,我们也曾经使用过级联的方式为其赋值,也就是通过类.属性的方式对其进行赋值,那么在spring中,也可以使用该方法吗?

如下所示:尝试使用类.属性的方式直接赋值:



运行结果如下:虽然上述这种方法可以在mybatis中使用,但是在spring中是不行的

在这里插入图片描述

使用级联方式的前提条件是:要保证提前为clazz属性赋值或者实例化

方法1:先赋值再修改



方法2:在student类中对clazz进行实例化

private  clazz clazz= new clazz( );

在spring.xml文件中可直接进行赋值:



无论上述那种方法,输出均为如下所示:

student{sid=1001, sname='张三', age=20, gender='男', clazz=clazz{cid=2222, name='卷心菜班'}}

虽然以级联的方式也可以对类类型进行赋值,但这种方法我们并不常用,我们通常使用内部bean的方式,下面我们就具体学习一下该方式如何使用:

使用内部bean的方式为类类型赋值:

修改spring.xml中的bean标签:



输出如下所示:

student{sid=1001, sname='张三', age=20, gender='男', clazz=clazz{cid=333, name='卷王班'}}

内部bean就类似于我们在java中学过的内部类一样,它只能在bean的内部进行使用,那么内部bean可以通过IOC容器进行获取吗?

修改测试类中的代码:

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import poij.clazz;public class student_text {@Testpublic void test(){ApplicationContext ioc=new ClassPathXmlApplicationContext( "spring.xml");clazz clazz1= ioc.getBean( clazz.class);System.out.println(clazz1);}
}

输出如下所示:

看来内部bean确实无法通过IOC容器直接获取

在这里插入图片描述

说到这里,为类类型的属性赋值的三种方式我们已经说完了,引用外部的bean以及使用内部bean是我们所推荐的方法,第二种使用级联并不是我们所推荐的,原因是,它需要先赋值再修改,这样好像并不是真正意义上的赋值,而是修改已有的值

依赖注入之为数组类型的属性赋值:

修改student类中的代码:

//添加新的属性
private  String [] hobby;//为新的属性编写set和get方法
public String[] getHobby() {return hobby;}public void setHobby(String[] hobby) {this.hobby = hobby;}
//重写toString方法@Overridepublic String toString() {return "student{" +"sid=" + sid +", sname='" + sname + '\'' +", age=" + age +", gender='" + gender + '\'' +", clazz=" + clazz +", hobby=" + Arrays.toString(hobby) +'}';}

在spring中为hobby属性赋值:

吃饭睡觉打豆豆

输出如下所示:

student{sid=1001, sname='张三', age=20, gender='男', clazz=clazz{cid=333, name='卷王班'}, hobby=[吃饭, 睡觉, 打豆豆]}

依赖注入之为集合类型的属性赋值:

修改clazz类:

//添加新的属性---1个班级可以有多个学生,因此将学生作为属性添加到班级中是以集合的形式
private List students;//为新的属性编写set和get方法
public List getStudents() {return students;}public void setStudents(List students) {this.students = students;}//重写toString方法@Overridepublic String toString() {return "clazz{" +"cid=" + cid +", name='" + name + '\'' +", students=" + students +'}';}

内部list集合为集合类型的属性赋值:

修改spring.xml文件:


吃饭睡觉
唱歌打游戏
弹钢琴跳舞


输出如下所示:

clazz{cid=111, name='软件1班', students=[student{sid=1, sname='张三', age=20, gender='女', clazz=null, hobby=[吃饭, 睡觉]}, student{sid=2, sname='李四', age=12, gender='男', clazz=null, hobby=[唱歌, 打游戏]}, student{sid=3, sname='lisa', age=21, gender='女', clazz=null, hobby=[弹钢琴, 跳舞]}]}

引用list集合的bean为集合类型的属性赋值:

如果在IOC容器中存在一个list集合类型的bean,那么我们是否可以直接通过ref来引用呢?如下所示:

在这里插入图片描述

上述这种方式是不对的, 我们现在要创建的是一个list集合类型的bean最主要的是要往list集合中去存储数据但如果我们单独创建一个bean,类型是ArrayList,我们能做的只是为当前这个类中的属性赋值,而不能通过bean标签为当前的这个集合去存取数据

正确方法:

当我们要配置一个集合类型的bean,需要使用util约束

添加前spring.xml文件中是没有该约束的:

在这里插入图片描述

添加之后新增util约束:

在这里插入图片描述

修改spring.xml文件中的内容:

吃饭睡觉唱歌打游戏弹钢琴跳舞

输出如下所示:

clazz{cid=111, name='软件1班', students=[student{sid=1, sname='张三', age=20, gender='女', clazz=null, hobby=[吃饭, 睡觉]}, student{sid=2, sname='李四', age=12, gender='男', clazz=null, hobby=[唱歌, 打游戏]}, student{sid=3, sname='lisa', age=21, gender='女', clazz=null, hobby=[弹钢琴, 跳舞]}]}

依赖注入之为map集合类型的属性赋值:

创建新的teacher类:

package poij;public class teacher {private  Integer tid;private  String name;public Integer getTid() {return tid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void setTid(Integer tid) {this.tid = tid;}public teacher() {}public teacher(Integer tid,String name) {this.tid = tid;this.name=name;}@Overridepublic String toString() {return "teacher{" +"tid=" + tid +", name='" + name + '\'' +'}';}
}

修改student:

//添加新的属性
private Map stringteacherMap;//为新添加的属性设置set和get方法public Map getStringteacherMap() {return stringteacherMap;}public void setStringteacherMap(Map stringteacherMap) {this.stringteacherMap = stringteacherMap;}//重写toString方法
@Overridepublic String toString() {return "student{" +"sid=" + sid +", sname='" + sname + '\'' +", age=" + age +", gender='" + gender + '\'' +", clazz=" + clazz +", hobby=" + Arrays.toString(hobby) +", stringteacherMap=" + stringteacherMap +'}';}

方法1:通过map标签进行设置

修改spring.xml文件:

假设我们现在要给id为student3的bean对象的stringteachermap属性赋值,如下所示,我们需要使用map标签而不是util:map,因为util:map的功能类似于util:list,它是用来配置一个类型为map的bean对象

在这里插入图片描述

由于map中的数据是以键值对的形式存取的,那么如何设置键值对呢?

在map标签中我们输入<,显示的结果有以下两种,看到entry不知道大家是否会感到格外的熟悉,因为这是我们在java中就已经接触过的,它表示的是一个类型,map中的键和值,我们可以使用一个entry来表示map集合中的一个键值对

在这里插入图片描述

entry中可包含的参数有以下几种:和我们上面学习的其他类型是一样的,凡是带有-ref的则证明这个参数的类型是一个对象,若仅仅是key和value,则证明这个参数是字面量

在这里插入图片描述


弹钢琴跳舞


方法2:通过util:map进行设置

对spring.xml进行修改:


弹钢琴跳舞

无论上述那种方法,输出均为如下所示:

student{sid=3, sname='lisa', age=21, gender='女', clazz=null, hobby=[弹钢琴, 跳舞], stringteacherMap={1号老师=teacher{tid=10086, name='大宝'}, 2号老师=teacher{tid=10010, name='小宝'}}}

依赖注入之为p命名空间:

在spring.xml文件中创建新的bean对象:


但我们使用上述这种p属性开头的方法,需要注意一定要引入p。它必须有约束的支持才能够进行,如下所示:

在这里插入图片描述

使用p:开头的这种方式,我们会发现每个属性都有两个一个是不带-ref后缀,一个是带-ref后缀,在前面的学习中,我们就说过带-ref表示该属性的值是一个类,而不带-ref的表示该属性的值是一个字面量

在这里插入图片描述

在测试类中获取id为student4的bean对象:

student student=ioc.getBean("student4", poij.student.class);
System.out.println(student);

输出如下所示,我们未赋值的属性是以null显示:

student{sid=12, sname='小白', age=null, gender='null', clazz=null, hobby=null, stringteacherMap={1号老师=teacher{tid=10086, name='大宝'}, 2号老师=teacher{tid=10010, name='小宝'}}}

这种方式虽然可行,但并不是常用的,因此我们了解一下即可!

相关内容

热门资讯

【java基础】Stream流... 文章目录基本介绍流的创建流的各种常见操作forEach方法filter方法map方法peek方法fl...
幂等性通用组件 一、什么是幂等性幂等是一个数学与计算机学概念,在数学中某一元运算为幂等时,...
Nacos服务注册 又是美好的一天呀~ 个人博客地址: huanghong.top 本文预估阅读时长为3...
令人惊艳的ChatGPT项目,... 自从 ChatGPT、Stable Diffusion 发布以来,各种相关开源项目百花...
舆情监测系统有哪些优势,TOO... 舆情监测系统是一种基于大数据技术的舆情分析工具,可以帮助企业、政府等机构实时监控公众对...
【Linux】基础IO流(上) 文章目录1. 预备知识2. 回忆C接口fopenfputsfprintfsnprintf追加方式——...
设计模式(二十七)----行为... 1 概述 如上图,设计一个软件用来进行加减计算。我们第一想法就是使用工具类ÿ...
精心整理前端主流框架学习路径 版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog....
typescript声明 前言 “d.ts”文件用于为 TypeScript 提供有关用 JavaScript 编写的 API...
HashMap源码分析 Java源码系列:下方连接 http://t.csdn.cn/Nwzed 文章目录...
一、基础算法3:二分 模板题+... 文章目录算法模板整数二分算法模板浮点数二分算法模板模板题数的范围原题链接题目题解数的三次方根原题链接...
Essential C++复习... 好久没写代码了,很多东西都忘记了。复盘一下C++编写基础头文件 与 输...
三十五、DRF中的过滤、Dja... 一、DRF中的过滤 REST framework 的通用列表视图的默认行为是返回模型管理器的整个查询...
基于RZ/G2UL Corte... 以太网接口是一种广泛应用的网络接口,它可以在不同的场合实现不同的功能。例如࿰...
nginx-会话保持-3 基于LNMP在负载均衡集群上部署wordpress(低配版) 在讲解会话...
【BBuf的CUDA笔记】九,... 0x0. 背景 随着年纪越来越大,读代码越来越困难,如果你发现看不懂同事...
springboot: myb... 目录 需求01:  根据不同类型 查询不同的订单名, 1. 书写订单 类型转换方法   2. 使用方...
最前端|什么是低代码?与传统开... 目录一、低代码介绍二、背景趋势三、低代码与传统代码开发(一)低代码能否替...
物流成本总是超标?一招教你降本... 先来看一个数据,中国仓储物流管理指标与世界标杆数据对比 第三方物流比例:...
exec家族与system函数 exec家族函数NAMEexecl, execlp, execle, execv, execvp, ...
Pots 倒水问题 简单搜索&&进阶搜索 - Virtual Judge (vjudge.net) 【题目描述】 两个...
Linux内核通杀提权漏洞(C... 之前Linux官方爆出了"脏牛"漏洞(代号:Dirty COW,漏洞编号...
如何解决“sxs.dll错误”... 在使用计算机的过程中,可能会遇到各种各样的错误。其中一个常见的错误是“sxs.dll错...
【数据结构】夯实基础|线性表刷... 作者:努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享...
自定义类型【C进阶】 文章目录😺结构体🟥结构体内存对齐内存对齐的规则内存对齐的意义修改默认...
latex 知识点总结 文章目录(一)latex 知识点总结(二)l...
【小猫爪】AUTOSAR学习笔... 【小猫爪】AUTOSAR学习笔记15-BswM模块前言1 BswM模块简介2 BswM功能简介2.1...
PMSM矢量控制笔记(1.2)... 前言:永磁同步电机的转子包括永磁体、转子铁芯、轴承等机械结构等,其转子可...
关于面试时HA(RAC)会问到... 1.什么是RAC(Real Application Cluster)&#...
关于车身广告的规定(车身广告是... 今天给各位分享关于车身广告的规定的知识,其中也会对车身广告是否合法进行解释,如果能碰巧解决你现在面临...