什么是依赖注入
在之前的学习中理解了IOC的概念
IOC的作用就是降低项目中的耦合(依赖关系)
但是在实际的项目中不可能完全消除耦合,这时候我们选择将依赖关系的管理都交给spring来维护。在当前类需要用到其他类的对象时,由spring给我们提供,而我们只需要在配置文件中说明。
下面主要记录以下知识点
依赖注入的数据有三类:
1.基本类型和String类型
2.其他bean类型
3.复杂类型/集合类型
注入的方式:
第一种:使用构造函数提供
第二种:使用set方法提供
第三种:使用注解提供(下次再写)
依赖注入基于配置文件的配置
1、使用构造函数提供依赖注入
使用的标签: constructor-arg
标签位置: bean标签内部
- 标签中的属性:
type: 用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型。(弊端:若构造函数中有两个相同的数据类型,就会注入失败)
index: 用于指定要注入的数据在构造函数中指定索引位置的参数赋值。索引位置从0开始。(弊端:需要准确的知道各个索引位置是什么属性,顺序不能打乱。)
name(常用): 用于指定给构造函数中指定名称的参数赋值。
(以上三个标签是用于指定给构造函数中哪个参数赋值)
value: 用于提供基本数据类新和String类型
ref: 用于指定其他bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象。
//创建一个test类,类中有三个属性
public class User {
private String name;
private Integer age;
private Date birthday;
//提供一个构造方法
public Test_o1(String name ,Integer age ,Date birthday){
this.name = name;
this.age = age;
this.birthday = birthday;
}
}
这时候根据之前的学习,我们应该在配置文件中配置这个类的bean
<bean id="user" class="com.tianqicode.User">
</bean>
完成之后,就该配置相应的属性注入了
<bean id="user" class="com.tianqicode.User">
<!-- 在这里配置属性的注入 -->
<constructor-arg name=“name” value=“tianqi”></constructor-arg>
<constructor-arg name=“age” value=“22”></constructor-arg>
<constructor-arg name=“birthday” value=“1997-04-16”></constructor-arg>
</bean>
这时候就可以在其他类使用这个类的对象了。
这时候出现了一个问题,因为value属性中无论是什么内容,spring都是以字符串的形式传入的,所以第三个属性注入会出现问题,这时候使用如下方式。
<bean id="user" class="com.tianqicode.User">
<!-- 在这里配置属性的注入 -->
<constructor-arg name=“name” value=“tianqi”></constructor-arg>
<constructor-arg name=“age” value=“22”></constructor-arg>
<!-- 使用ref属性调用-->
<constructor-arg name=“birthday” ref=“now”></constructor-arg>
</bean>
<!-- 在这里配置一个日期对象 -->
<bean id="now" class="java.util.date"></bean>
这时候再在其他类调用这个类的对象,就可以正常使用了
这种方式的优劣:
优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功
弊端:改变了bean对象的实例化方式,是我们在创建对象时,如果用不到这些数据,也必须提供。
set方法注入(常用)
2、使用set方法提供依赖注入
使用的标签: property
出现的位置: bean标签的内部
- 标签的属性:
name(常用): 用于指定注入时所调用的方法名称。
value: 用于提供基本数据类新和String类型。
ref: 用于指定其他bean类型数据。它指的就是在spring的IOC核心容器中出现过的bean对象。
package com.tianqicode;
//依然准备一个类
import java.util.Date;
public class User {
private String name;
private Integer age;
private Date birthday;
//提供set/get方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
这时候修改配置文件中的内容
<bean id="user" class="com.tianqicode.User">
<!-- 在这里配置属性的注入 -->
<property name=“name” value=“tianqi”></property>
<property name=“age” value=“22”></property>
<!-- 使用ref属性调用-->
<property name=“birthday” ref=“now”></property>
</bean>
<!-- 在这里配置一个日期对象 -->
<bean id="now" class="java.util.date"></bean>
那么这种方式的优劣:
优势:创建对象时没有明确的限制,只需要调用默认的构造方法即可。
弊端:如果有某个成员必须有值,则获取对象时是有可能set方法没有执行。
注入集合数据
这里将注入集合数据单独拿出来记录一下。
//依然准备类,修改一下其中的属性为一些常用的容器对象。
package com.tianqicode;
import java.util.*;
public class User1 {
private String[] myStrs;
private List<String> myList;
private Set<String> mySet;
private Map<String, String> myMap;
private Properties myProperties;
public String[] getMyStrs() {
return myStrs;
}
public void setMyStrs(String[] myStrs) {
this.myStrs = myStrs;
}
public List<String> getMyList() {
return myList;
}
public void setMyList(List<String> myList) {
this.myList = myList;
}
public Set<String> getMySet() {
return mySet;
}
public void setMySet(Set<String> mySet) {
this.mySet = mySet;
}
public Map<String, String> getMyMap() {
return myMap;
}
public void setMyMap(Map<String, String> myMap) {
this.myMap = myMap;
}
public Properties getMyProperties() {
return myProperties;
}
public void setMyProperties(Properties myProperties) {
this.myProperties = myProperties;
}
}
然后在配置文件中添加容器的配置
<bean id="user1" class="com.tianqicode.User1">
<!-- 使用set方法注入的方式 -->
<property name="myStrs">
<!-- 在property标签下添加相应子标签 -->
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
......
</bean>
其他属性的注入也是相同的格式
标签的使用细节:
- 用于给List结构集合注入的标签:
list
array
set - 用于给Map结构集合注入的标签:
map
props
结构相同的话,标签可以互换。