Spring 依赖注入详解(Dependency Injection)
我们知道spring中的一个核心内容就是ioc控制反转,作用是降低程序间的耦合(依赖关系),所以我们对于程序间的依赖关系管理都交给Spring框架来管理维护,所以,在类中需要其他类的对象,由spring为我们提供,我们只需要在配置文件中说明,spring这种对于依赖关系的维护,我们就称作为依赖注入。
依赖注入可以注入的数据:
- 基本类型和String
- 其他的bean类型
- 集合等复杂类型
依赖注入的注入方式:
1.构造函数注入:
要注入的目标类:
package com.jack.service.imp;
import com.jack.dao.AccountDao;
import com.jack.service.AccountService;
import java.util.Date;
/**
* @Author: jack
* @date: 2019/10/21 21:44
*/
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao;
/**
* 构造函数注入测试,(经常变化的数据不适合使用构造函数注入)
*/
private String test1;
private Integer test2;
private Date test3;
public AccountServiceImpl(String test1, Integer test2, Date test3) {
this.test1 = test1;
this.test2 = test2;
this.test3 = test3;
}
public String findAll() {
return accountDao.findAll();
}
@Override
public String toString() {
return "AccountServiceImpl{" +
"test1='" + test1 + '\'' +
", test2=" + test2 +
", test3=" + test3 +
'}';
}
}
配置文件:
<bean id="accountService" class="com.jack.service.imp.AccountServiceImpl">
<constructor-arg type="java.lang.String" value="String类型的注入测试"/>
<constructor-arg name="test2" value="111"/>
<constructor-arg name="test3" ref="now"/>
</bean>
<bean id="now" class="java.util.Date"/>
测试结果:
这是一个简单的例子,这里我们来介绍一下这些标签的具体含义:
构造函数注入:
使用的标签:constructor-arg
标签使用的位置:bean标签内部
标签中的属性:
type:用于指定要注入的数据的数据类型,即根据类型给参数赋值,若存在多个参数类型相同,单独使用type无法赋值。
index:用于指定要注入的数据给构造函数中的哪个位置的参数赋值,索引从0开始,即根据位置给参数赋值
name:用于给指定构造函数中的哪个名称的参数赋值,即根据名称给参数赋值 (常用)
value:用于给基本类型和String类型赋值
ref:用于指定其他的bean类型的数据。必须得是配置文件中注册过的。
构造函数注入的优缺点:
优势:
在获取bean对象时,注入数据时必须的操作,不然无法创建对象,这种方式对于一些不发生变化的数据,免于被使用者遗忘。
劣势:
改变了bean对象的实例化方式,当我们创建对象时,哪怕其中有些数据我们暂时用不上,或者不用,也必须提供这些数据,少一个都创建不了。
2.set方法注入:
配置文件:
<bean id="accountServiceImpl2" class="com.jack.service.imp.AccountServiceImpl2">
<property name="test1" value="set方法注入测试"/>
<property name="test2" value="111"/>
<property name="test3" ref="now"/>
</bean>
注入的目标类:
package com.jack.service.imp;
import com.jack.dao.AccountDao;
import com.jack.service.AccountService;
import java.util.Date;
/**
* @Author: jack
* @date: 2019/10/21 21:44
*/
public class AccountServiceImpl2 implements AccountService {
private AccountDao accountDao;
private String test1;
private Integer test2;
private Date test3;
public void setTest1(String test1) {
this.test1 = test1;
}
public void setTest2(Integer test2) {
this.test2 = test2;
}
public void setTest3(Date test3) {
this.test3 = test3;
}
public String findAll() {
return accountDao.findAll();
}
@Override
public String toString() {
return "AccountServiceImpl{" +
"test1='" + test1 + '\'' +
", test2=" + test2 +
", test3=" + test3 +
'}';
}
}
顾名思义:set方法注入必须得有set方法。
测试结果:
介绍一下标签的含义:
涉及的标签:property
出现的位置:bean标签中
标签的属性:
name:用于指定set方法的名称
value:和构造函数相同,用于设置数据
ref:用于指定其他的bean类型的数据。必须得是配置文件中注册过的。
set方法注入的优缺点正好跟构造方法相反
优势:
创建对象时没有明确的限制,可以直接使用默认构造函数
劣势:
如果有某个成员必须有值,则获取对象时不能保证值的存在
另一种注解注入方式,我们以后再讲。
集合数据及复杂类型注入
配置文件:
<bean id="accountServiceImpl3" class="com.jack.service.imp.AccountServiceImpl3">
<!--数组注入-->
<property name="strings">
<array>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</array>
</property>
<!--list注入-->
<property name="list">
<list>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</list>
</property>
<!--set注入-->
<property name="set">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<!--map注入-->
<property name="map">
<map>
<entry key="aaa" value="AAA"/>
<entry key="bbb" value="BBB"/>
<entry key="ccc" value="CCC"/>
</map>
</property>
<!--properties注入-->
<property name="properties">
<props>
<prop key="a">AAA</prop>
<prop key="b">BBB</prop>
<prop key="c">CCC</prop>
</props>
</property>
</bean>
注入目标类
private String[] strings;
private List<String> list;
private Set<String> set;
private Map<String,String> map;
private Properties properties;
public String findAll() {
System.out.println(Arrays.toString(strings));
System.out.println(list);
System.out.println(set);
System.out.println(map);
System.out.println(properties);
return null;
}
public void setStrings(String[] strings) {
this.strings = strings;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
输出结果:
总结一下:
用于给list结构集合注入的标签:
list array set
用于给map结构集合注入的标签:
map prop
注意,这里我虽然注入时id,类型和实体类中对应的属性都相同,但实际情况是,结构相同可以互换。
所以我们只要记住一组list 和一组 map 的.