依赖注入(Dependency
Injection,简称DI)与控制反转(IoC)的含义相同,只不过这两个称呼是从两个角度描述同一个概念。下面通过简单地语言来进行描述
概念
- 通常情况下,调用者会采用"new被调用者"的代码方式来创建对象,如下图。但这种方式会导致调用者与被调用者之间的耦合性增加,不利于后期项目的升级和维护。
- 而使用了Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring容器会负责控制程序之间的关系。这样控制权便由应用代码转移到Spring容器,控制权发生了反转,这就是Spring的控制反转
- 从Spring容器来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这就相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入
实现方式
能注入的数据:有三类
- 基本类型和String
- 其他bean类型(在配置文件中或者注解配置过的bean)
- 复杂类型/集合类型
注入的方式:有三种
- 使用构造函数提供
- 使用set方法提供
- 第三种:使用注解提供
构造函数注入:
使用的标签:constructor-arg
标签出现的位置:bean标签的内部
标签中的属性
type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型
index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值。索引的位置是从0开始
name:用于指定给构造函数中指定名称的参数赋值 常用的
=以上三个用于指定给构造函数中哪个参数赋值===================
value:用于提供基本类型和String类型的数据
ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
优势:
在获取bean对象时,注入数据是必须的操作,否则对象无法创建成功。
弊端:
改变了bean对象的实例化方式,使我们在创建对象时,如果用不到这些数据,也必须提供。
步骤:
- 创建一个Maven Project,并在pom.xml中配置spring框架
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>day01_eesy_04Spring</groupId>
<artifactId>day01_spring04</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
</dependencies>
- 在com.itheima.service包中创建接口IUserService接口,在接口中编写say()方法
public interface IUserService {
void say();
}
- 在com.itheima.service.Impl包中创建IUserService接口的实现类UserServiceImpl,在类中声明name、id、birthday属性,并添加对应方法
public class UserServiceImpl implements IUserService {
private Integer id;
private String username;
private Date birthday;
public UserServiceImpl(Integer id, String username, Date birthday) {
this.id = id;
this.username = username;
this.birthday = birthday;
}
public void say() {
System.out.println("id="+id+",username="+username+",birthday="+birthday);
}
}
- 在resource中编写配置文件bean.xml,创建id为userservice的Bean,该Bean用于实例化UserServiceImpl类的信息,注意的是,当要输出类型为date时要创建一个新的bean在通过ref获取
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="userservice" class="com.itheima.service.Impl.UserServiceImpl">
<constructor-arg name="username" value="张三"></constructor-arg>
<constructor-arg name="id" value="36"></constructor-arg>
<constructor-arg name="birthday" ref="now"></constructor-arg>
</bean>
<bean id="now" class="java.util.Date"></bean>
</bean>
- 在com.itheima.ui中创建Client,来对程序进行测试
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
UserServiceImpl userService = (UserServiceImpl) applicationContext.getBean("userservice");
userService.say();
}
}
控制台输出结果如下
set方法注入 更常用的方式
- 涉及的标签:property
- 出现的位置:bean标签的内部
- 标签的属性
- name:用于指定注入时所调用的set方法名称
- value:用于提供基本类型和String类型的数据
- ref:用于指定其他的bean类型数据。它指的就是在spring的Ioc核心容器中出现过的bean对象
优势:创建对象时没有明确的限制,可以直接使用默认构造函数
弊端:如果有某个成员必须有值,则获取对象是有可能set方法没有执行。
<!-- 复杂类型的注入/集合类型的注入
用于给List结构集合注入的标签:
list array set
用于个Map结构集合注入的标签:
map props
结构相同,标签可以互换
-->
步骤:
- 在上一个的基础上在com.itheima.service.Impl包中创建IUserService接口的实现类UserServiceImpl3,在类中声明name、id、birthday属性,并添加对应方法
public class UserServiceImpl3 implements IUserService {
private List<String> list;
private String[] strings;
private Map<String,String> map;
private Properties properties;
private Set<String> set;
public void setList(List<String> list) {
this.list = list;
}
public void setStrings(String[] strings) {
this.strings = strings;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void say() {
System.out.println(Arrays.toString(strings));
System.out.println(list);
System.out.println(set);
System.out.println(map);
System.out.println(properties);
}
}
- 在bean.xml中再创建一个id为userservice02的Bean,该Bean用于实例化UserServiceImpl类中的信息
<bean id="userservice02" class="com.itheima.service.Impl.UserServiceImpl3">
<property name="strings">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<property name="list">
<array>
<value>listA</value>
<value>listB</value>
<value>listC</value>
</array>
</property>
<property name="set">
<set>
<value>AAA</value>
<value>BBB</value>
<value>CCC</value>
</set>
</property>
<property name="map">
<props>
<prop key="Test1">hehe</prop>
<prop key="Test2">haha</prop>
</props>
</property>
<property name="properties">
<props>
<prop key="protertie1">ppp1</prop>
<prop key="protertie2">ppp2</prop>
</props>
</property>
</bean>
- 在com.itheima.ui中创建Client02,来对程序进行测试
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
UserServiceImpl3 userService = (UserServiceImpl3) applicationContext.getBean("userservice02");
userService.say();
}
}
在控制台的输出结果如下