依赖注入(DI)是一个过程,在这个过程中,对象仅通过构造函数参数、工厂方法的参数或在对象被实例化后通过属性设置来定义它们的依赖项(即与该对象一起工作的其他对象)。然后,容器在创建 bean 时注入这些依赖项。这个过程基本上是与对象直接通过构造类或等机制来控制其依赖项的实例化或位置是相反的,因此得名控制反转。// 对象不直接创建自己,而是通过 Spring 容器创建,那么 Spring 容器是如何创建对象的?
使用 DI 原则,代码会更简洁,当对象具有依赖关系时,也能更有效的解耦。对象不检索它的依赖项,也不知道依赖项的具体类或者位置。因此,你的类将变得更容易测试,特别是当依赖关系建立在接口或者抽象基类上时,他们的子类或者模拟实现将允许在单元测试中被使用。// 依赖注入最大的好处,就是代码可以解耦合变得更加简洁
DI 主要有两种变体:基于构造函数的依赖注入和基于 Setter 方法的依赖注入
基础环境
1.创建Module
2.引入依赖
<?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">
<parent>
<artifactId>spring</artifactId>
<groupId>com.biem</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>DI</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
3. 创建实体类com.biem.spring.pojo.User.java
package com.biem.spring.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* ClassName: User
* Package: com.biem.spring.pojo
* Description:
*
* @Create 2023/5/25 18:07
* @Version 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private int id;
private String name;
private String password;
}
4. 创建applicationContext.xml配置文件
<?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">
</beans>
4. 测试com.biem.spring.test.UserTest.java文件
package com.biem.spring.test;
import com.biem.spring.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* ClassName: UserTest
* Package: com.biem.spring.test
* Description:
*
* @Create 2023/5/25 18:13
* @Version 1.0
*/
public class UserTest {
}
基于构造函数的依赖注入
<constructor-arg>元素用于构造方法的注入,且定义时不分顺序,只需要通过name属性指定值即可。<constructor-arg>还提供了type属性用于指定参数类型,以避免字符串和基本类型的混淆。
实例
1.applicationContext.xml添加
<bean id="user1" class="com.biem.spring.pojo.User">
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="password" value="123456"></constructor-arg>
</bean>
2. com.biem.spring.test.UserTest.java添加
@Test
public void testConstructorDI(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean("user1", User.class);
System.out.println("user = " + user);
}
3.输出结果
基于 Setter 方法的依赖注入
setter方法注入是通过<property>元素,<property>元素过name属性指定值。
实例
1.applicationContext.xml添加
<bean id="user2" class="com.biem.spring.pojo.User">
<property name="id" value="2"></property>
<property name="name" value="李四"></property>
</bean>
2. com.biem.spring.test.UserTest.java添加
@Test
public void testSetterDI(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = context.getBean("user2", User.class);
System.out.println("user = " + user);
}
3.输出结果
Null值处理
<property name="name">
<null />
</property>
name的值是null
<property name="name" value="null"></property>
name的值是字符串null