依赖注入(Dependency Injection,DI)是 Spring 框架的核心特性之一,也是 Spring 实现控制反转(Inversion of Control,IoC)的重要手段。
依赖注入可以帮助我们解耦应用程序中的各个组件,使得这些组件可以更加灵活地组合和重用。
要理解什么是依赖注入,就要先知道什么是依赖。依赖就是当我们创建了两个类,A类和B类,当我们在A类中创建了B类的实例,也就是在A类中 new B类的对象了。因为A类是要使用B类中的某些属性,所以这时候A类就依赖与B类。但是这种写法的耦合性十分严重,因为如果B类中的属性发生变化,那么引用B类实例的A类也会受到影响,所以出现了IoC容器,将实例的创建与管理交给Spring IoC容器,在通过依赖注入来实现控制反转,达到解耦的目的。
依赖注入可以注入的类型
基本类型和String字符串
其他 bean类型(在配置文件中或者注解配置过的bean)。
复杂类型/集合类型。
实现依赖注入的方式: 在JDK5.0之前,实现依赖注入的方式有构造函数注入、Setter 方法注入。下面是通过 Char GPT 查询的依赖注入的注入方式相关文档
在 Spring 框架中,可以通过构造函数注入和 Setter 方法注入来实现依赖注入,并通过 XML 配置文件或注解的方式来配置依赖关系。
构造函数注入:构造函数注入是一种最常见的依赖注入方式。在构造函数注入中,我们通过构造函数将依赖关系注入到目标对象中。例如,我们可以在构造函数中声明一个接口类型的参数,然后在 Spring 容器中配置该接口的具体实现类,Spring 容器会自动将该实现类注入到构造函数中。
Setter 方法注入:Setter 方法注入是另一种常见的依赖注入方式。在 Setter 方法注入中,我们通过 Setter 方法将依赖关系注入到目标对象中。例如,我们可以在目标对象中声明一个接口类型的属性,并提供一个 Setter 方法,然后在 Spring 容器中配置该接口的具体实现类,Spring 容器会自动调用 Setter 方法,将该实现类注入到目标对象中。
无论是构造函数注入还是 Setter 方法注入,Spring 框架都可以通过 XML 配置文件或注解的方式来实现依赖注入。在 XML 配置文件中,我们可以通过 标签来声明目标对象和依赖关系,并通过 ref 属性来指定依赖关系的具体实现类。
使用构造函数注入: 当我们通过配置文件配置指定的类时,也就是Bean,Spring 会找到该类的构造方法,通过构造方法给成员变量赋值,这个注入过程完全由 Spring控制。
代码实例:实例一:二、Spring 控制反转(IOC)学习总结中4.4章节
实例二:创建一个子模块,在子模块中创建 User 实体类,不添加Set、get方法,创建有参构造和toString()
public class User {
private String str;
private String age;
private String name;
public User(String name,String str,String age){
this.name = name;
this.str = str;
this.age = age;
}
public void show(){
System.out.println("name:" + name);
System.out.println("age:" + age);
System.out.println("str:" + str);
}
}
创建 Beans.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.sys.dto.User">
<constructor-arg index="1" value="在慵懒的生活中学习Java"/>
<constructor-arg name="name" value="姚青"/>
<constructor-arg type="java.lang.String" value="24"/>
</bean>
</beans>
创建 MyTest
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
User user = (User) context.getBean("user");
user.show();
}
}
使用 Setter 方法注入: 通过反射调用set ()进行注入,所以要注入的实体类属性要有相对应的set方法
依赖注入本质上就是Set注入,底层是通过Set()来实现的。
依赖:bean对象的创建依赖于容器!
注入:bean对象中的所有属性,由容器来注入!
ref 标签: 对应ref属性,该标签name属性的属性值为另一个bean标签id或name属性的属性值;
array 标签: 为数组类型参数赋值;
value 标签: 对应value属性,用于设置基本数据类型或String类型的参数值;
list 标签: 为数组或List类型的参数赋值
set 标签: 为Set集合类型参数赋值
map 标签: 为Map集合类型参数赋值
props 标签: 为Properties类型的参数赋值
通过 Set 注入复杂类型和集合类型数据
创建一个子模块,与子模块中创建对应路径,创建 UserInfo 实体类
public class UserInfo {
// 使用Set注入的方式对各种类型数据进行注入
private String name;// 字符串
private Address address;// 引用类型
private String[] books;// 数组类型
private List<String> hobbys; // List 集合类型
private Map<String, String> card;// Map 集合类型
private Set<String> games;// Set 集合类型
private String wife;
private Properties info;// 引用类型
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Address getAddress() {return address; }
public void setAddress(Address address) {this.address = address;}
public String[] getBooks() {return books;}
public void setBooks(String[] books) {this.books = books;}
public List<String> getHobbys() {return hobbys;}
public void setHobbys(List<String> hobbys) {this.hobbys = hobbys;}
public Map<String, String> getCard() {return card;}
public void setCard(Map<String, String> card) {this.card = card;}
public Set<String> getGames() {return games;}
public void setGames(Set<String> games) {this.games = games;}
public String getWife() {return wife;}
public void setWife(String wife) {this.wife = wife; }
public Properties getInfo() {return info;}
public void setInfo(Properties info) {this.info = info; }
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", games=" + games +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
创建 Address 实体类
public class Address {
private String address;
public String getAddress() {return address;}
public void setAddress(String address) {this.address = address;}
}
创建 Beans.xml
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.sys.dto.Address">
<property name="address" value="该用户来自外太空"/>
bean>
<bean id="userInfo" class="com.sys.dto.UserInfo">
<property name="name" value="姚青"/>
<property name="address" ref="address"/>
<property name="learnContent">
<array>
<value>JAVAvalue>
<value>Mysqlvalue>
<value>Springvalue>
<value>Vuevalue>
array>
property>
<property name="hobbys">
<list>
<value>打游戏value>
<value>在森林公园散步value>
<value>躺在雪地里看天value>
list>
property>
<property name="games">
<set>
<value>王者荣耀value>
<value>口袋妖怪value>
set>
property>
<property name="card">
<map>
<entry key="education" value="本科"/>
<entry key="age" value="24"/>
map>
property>
<property name="wife">
<null/>
property>
<property name="info">
<props>
<prop key="blogType">CSDNprop>
<prop key="blogUrl">https://blog.csdn.net/shiyu_951/article/details/123269378prop>
props>
property>
bean>
beans>
创建 SetterMyTest 测试类
public class SetterMyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
UserInfo student = (UserInfo) context.getBean("userInfo");
System.out.println("姓名:" + student.getName());
System.out.println("住址:" + student.getAddress().getAddress());
System.out.println("学习内容:" + Arrays.toString(student.getLearnContent()));
System.out.println("爱好:" + student.getHobbys());
System.out.println("喜欢的游戏:" + student.getGames());
System.out.println("身份信息:" + student.getCard());
System.out.println("是否婚配:" + student.getWife());
System.out.println("博客信息:" + student.getInfo());
}
}
扩展
Java Properties 是一种用于存储和读取配置文件的数据结构,它继承自 Hashtable 类,可以保存一些键值对的配置信息,例如数据库连接信息、系统参数等。
Properties 对象中的键和值都是字符串类型的,它提供了一些方法来读取和设置键值对,比如 getProperty()、setProperty()、load()、store() 等方法。