文章目录
- 一、依赖注入
- 1.1 构造函数注入
- 1.2 Setter 方法注入(重点掌握)
- 1.2.1 通过 Set 注入复杂类型和集合类型数据
一、依赖注入
依赖注入(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 属性来指定依赖关系的具体实现类。
1.1 构造函数注入
-
使用构造函数注入: 当我们通过配置文件配置指定的类时,也就是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(); } }
-
运行结果
-
-
1.2 Setter 方法注入(重点掌握)
-
使用 Setter 方法注入: 通过反射调用set ()进行注入,所以要注入的实体类属性要有相对应的set方法
-
依赖注入本质上就是Set注入,底层是通过Set()来实现的。
-
依赖:bean对象的创建依赖于容器!
-
注入:bean对象中的所有属性,由容器来注入!
-
-
1.2.1 通过 Set 注入复杂类型和集合类型数据
-
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
<?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="address" class="com.sys.dto.Address"> <property name="address" value="该用户来自外太空"/> </bean> <!-- 使用 Set注入复杂类型和集合类型数据 --> <bean id="userInfo" class="com.sys.dto.UserInfo"> <!-- 第一种:字符串注入,直接用value注入 --> <property name="name" value="姚青"/> <!-- 第二种:注入引用类型数据,使用ref来注入 --> <property name="address" ref="address"/> <!-- 第三种:注入数组类型数据 --> <property name="learnContent"> <array> <!-- 注:value注入的数据类型与实体类属性类型一致 --> <value>JAVA</value> <value>Mysql</value> <value>Spring</value> <value>Vue</value> </array> </property> <!-- 第四种:注入 List 集合类型数据 --> <property name="hobbys"> <list> <value>打游戏</value> <value>在森林公园散步</value> <value>躺在雪地里看天</value> </list> </property> <!-- 第五种:注入Set 集合类型数据 --> <property name="games"> <set> <value>王者荣耀</value> <value>口袋妖怪</value> </set> </property> <!-- 第六种:注入Map 集合类型数据 --> <property name="card"> <map> <entry key="education" value="本科"/> <entry key="age" value="24"/> </map> </property> <!-- 第七种:注入 为 NULL 的数据 --> <property name="wife"> <null/> </property> <!-- 第八种:注入 Properties 类型数据 --> <property name="info"> <props> <prop key="blogType">CSDN</prop> <prop key="blogUrl">https://blog.csdn.net/shiyu_951/article/details/123269378</prop> </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() 等方法。