Spring——依赖注入(DI)详解
- 2019 年 10 月 3 日
- 筆記
声明:本博客仅仅是一个初学者的学习记录、心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流、一起学习、一起进步的朋友可以加我微信Liu__66666666
这是简单学习一遍之后的记录,后期还会修改。
一、概念引入
我们通过前文Spring——IOC已经知道怎么创建一个空白的实例对象,但是这个实例对象是没有进行任何成员变量设置的,都是默认值,例如int类型默认为0、引用类型默认为null。
那我们如果想创建带有特定属性的对象,那现在有个Computer类,他有属性”型号“。所以出厂的时候这个属性就是早被设定好了,那代码中的工厂如何去设置这个属性呢?其实依赖注入(DI,Dependency Injection)所做的工作就是为Spring中的Bean设置属性(成员变量的值)。
百度百科概念:所谓依赖注入,是指程序运行过程中,如果需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部的注入。Spring的依赖注入对调用者和被调用者几乎没有任何要求,完全支持对POJO之间依赖关系的管理。
二、依赖注入方式
依赖注入常见的有三种:
- 通过构造方法注入 - setter方法注入 - 接口注入
现在有苹果电脑公司的“MacBook pro 2019”型号的电脑都是“macOS Mojave”系统,那该怎么设置型号和操作系统这两个属性呢?下面我们就以这个电脑为例探讨一下!
首先建好项目并导入jar包,创建好applicationContext.xml文件,操作步骤参考Spring——IOC
项目目录结构如下:
Computer类:
public class Computer { private String type;//电脑型号 private OperatingSystem operatingSystem;//操作系统 public Computer() {} public Computer(String type, OperatingSystem operatingSystem) { this.type = type; this.operatingSystem = operatingSystem; } //此处略去getter setter toString方法 }
OperatingSystem类(这是Computer的一个属性:操作系统)
public class OperatingSystem { private String name;//操作系统名字,例如Windows、macOS //操作系统版本,例如,当name为Windows,version为10的时候,就是win10 private String version; public OperatingSystem(){} public OperatingSystem(String name, String version) { this.name = name; this.version = version; } //此处略去getter setter toString方法 }
1.构造方法注入(一定要写对应的构造方法!)
此方式使用的是bean标签内部的
以如下构造方法为例
public Computer(String type, OperatingSystem operatingSystem) { this.type = type; this.operatingSystem = operatingSystem; }
- 写法1(不推荐,不常用):
<!--macOS mojave--> <bean id="operatingSystem" class="di.OperatingSystem"> <constructor-arg index="0" value="macOS"/> <constructor-arg index="1" value="Mojave"/> </bean> <bean id="computer" class="di.Computer"> <constructor-arg index="0" value="MacBook Pro 2019"/> <constructor-arg index="1" ref="operatingSystem"/> </bean>
每个constructor-arg标签代表构造方法中的一个参数;
属性index代表参数的顺序,从0开始,index=“0”代表的是构造方法的String type这个参数,index=“1”代表的是OperatingSystem这个参数;
属性value代表的是这个参数要传入的值,例如type这个参数对应的是macOS,version是Mojave,一般来说,基本类型和String类型要用value属性来传值。
由于在Computer类中我们引用了OperatingSystem这个对象,所以需要先定义好OperatingSystem这个bean,以供我们将其注入到computer这个bean中,其实OperatingSystem就是Computer的一个依赖。而在第二个bean中,有一个ref属性,这个用来传value传不了的值,ref在本例中的值为operatingSystem这个bean的id。
- 写法2(推荐写法,但不常用):
<!--macOS mojave--> <bean id="operatingSystem" class="di.OperatingSystem"> <constructor-arg name="name" value="macOS"/> <constructor-arg name="version" value="Mojave"/> </bean> <bean id="computer" class="di.Computer"> <constructor-arg name="type" value="MacBook Pro 2019"/> <constructor-arg name="operatingSystem" ref="operatingSystem"/> </bean>
其他地方与写法1一样,唯一区别就是将写法1中的index属性换成了name属性,这样直接通过参数名来确定,清晰明了,不容易出错。
2.setter方法注入(一定要写好空参构造和所有属性的setter方法!!!)
此方式使用的是bean标签内部的
以如下构造方法为例
public Computer(String type, OperatingSystem operatingSystem) { this.type = type; this.operatingSystem = operatingSystem; }
注入:
<!--macOS mojave--> <bean id="operatingSystem" class="di.OperatingSystem"> <property name="name" value="macOS"/> <property name="version" value="Mojave"/> </bean> <bean id="computer" class="di.Computer"> <property name="type" value="MacBook Pro 2019"/> <property name="operatingSystem" ref="operatingSystem"/> </bean>
其实与构造函数注入的第二种方式差不多,只不过是把
3.接口注入(没用,不说了)
三、集合注入
注意:下文中的value标签,当需要设的值是自己定义的bean时,要用将
为Computer类新增属性keys,表示键盘上的键的集合。
1.数组与List(可互相替换)
其实Spring中将Array和List等同起来了。
写法1(constructor-arg + array):
<bean id="computer" class="di.Computer"> <constructor-arg name="keys"> <array> <value>a</value> <value>b</value> <value>c</value> </array> </constructor-arg> </bean>
写法2(constructor-arg + list):
<bean id="computer" class="di.Computer"> <constructor-arg name="keys"> <list> <value>a</value> <value>b</value> </list> </constructor-arg> </bean>
写法3(property + array):
<bean id="computer" class="di.Computer"> <property name="keys"> <array> <value>a</value> <value>b</value> </array> </property> </bean>
写法4(property + list):
<bean id="computer" class="di.Computer"> <property name="keys"> <list> <value>a</value> <value>b</value> </list> </property> </bean>
2.Set
写法1(constructor-arg):
<bean id="computer" class="di.Computer"> <constructor-arg name="keys"> <set> <value>a</value> <value>b</value> </set> </constructor-arg> </bean>
写法2(property):
<bean id="computer" class="di.Computer"> <property name="keys"> <set> <value>a</value> <value>b</value> </set> </property> </bean>
3.Map
为Computer类新增属性map<String,String> sofewares,key表示软件,value表示软件安装目录
为Computer类新增属性map<String,Singer> songs,key表示歌曲名,value表示歌手对象
写法1(property):
<bean id="singerEdSheeran" class="di.Singer"> <property name="name" value="Ed Sheeran"/> </bean> <bean id="computer" class="di.Computer"> <property name="softwares"> <map> <entry key="WeChat" value="/Users/...."/> <entry key="Intellij Idea" value="/usr/local/...."/> </map> </property> <property name="songs"> <map> <entry key="Shape of You" value-ref="singerEdSheeran"/> <entry key="I dont care" value-ref="singerEdSheeran"/> </map> </property> </bean>
写法2(将写法1的property换成constructor-arg即可)
注意,如果key或value要引用其他bean,那么对应地需要将