0%

Spring5.x学习笔记2——注入

Spring5.x学习笔记2——注入

什么是注入?

注入:通过 Spring 工厂及配置文件,为所创建对象的成员变量赋值。

为什么要注入?

  • 通过编码的⽅式,为成员变量进⾏赋值,存在耦合。
  • 注入的好处:解耦合
1
2
3
4
5
6
7
8
9
public void test4() {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
Person person = (Person) ctx.getBean("person");
// 通过代码为变量赋值, 存在耦合, 如果我们以后想修改变量的值, 需要修改代码, 重新编译
person.setId(1);
person.setName("zhenyu");
System.out.println(person);
}
12345678

如何进行注入[开发步骤]

  • 类的成员变量提供 set get ⽅法
  • 配置 spring 的配置⽂件
1
2
3
4
5
6
7
8
9
<bean id="person" name="p" class="com.yusael.basic.Person">
<property name="id">
<value>10</value>
</property>
<property name="name">
<value>yusael</value>
</property>
</bean>
12345678

Spring注入的原理分析(简易版)

Spring 底层通过调用对象属性对应的 set 方法,完成成员变量的赋值,这种⽅式也称为 Set注入
在这里插入图片描述

Set注入详解

Set注入的变量类型

  • JDK内置类型
    8种基本类型 + String、数组类型、set集合、list集合、Map计划和、Properties集合。
  • 用户自定义类型

针对于不同类型的成员变量,在<property标签中,需要嵌套其他标签:

1
2
3
4
<property>
xxxxx
</property>
123

在这里插入图片描述

JDK内置类型

  • String+8种基本类型
1
2
3
4
5
6
7
<property name="id">
<value>10</value>
</property>
<property name="name">
<value>yusael</value>
</property>
123456
  • 数组
1
2
3
4
5
6
7
8
<property name="emails">
<list>
<value>abc@qq.com</value>
<value>123@qq.com</value>
<value>hello@qq.com</value>
</list>
</property>
1234567
  • Set集合
1
2
3
4
5
6
7
8
<property name="tels">
<set>
<value>138xxxxxxxxxx</value>
<value>139xxxxxxxxxx</value>
<value>138xxxxxxxxxx</value><!--set会自动去重-->
</set>
</property>
1234567
  • List集合
1
2
3
4
5
6
7
8
<property name="addresses">
<list>
<value>China</value>
<value>Earth</value>
<value>hell</value>
</list>
</property>
1234567
  • Map集合
1
2
3
4
5
6
7
8
9
10
11
12
13
<property name="qqs">
<map>
<entry>
<key><value>hello</value></key>
<value>12312312312</value>
</entry>
<entry>
<key><value>world</value></key>
<value>21314214214</value>
</entry>
</map>
</property>
123456789101112
  • Properites
1
2
3
4
5
6
7
8
<property name="p">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
<prop key="key3">value3</prop>
</props>
</property>
1234567
  • 复杂JDK类型(Date、…)

需要程序员⾃定义类型转换器,处理。

用户自定义类型

第一种方式

[开发步骤]:

  • 为成员变量提供 set get ⽅法
  • 配置⽂件中进⾏注入(赋值)
1
2
3
4
5
6
<bean id="userService" class="com.yusael.service.UserServiceImpl">
<property name="userDAO">
<bean class="com.yusael.dao.UserDAOImpl"/>
</property>
</bean>
12345

第二种方式

第⼀种赋值⽅式存在的问题:

  1. 配置⽂件代码冗余;
  2. 被注入的对象 (UserDAO)多次创建,浪费(JVM)内存资源。

[开发步骤]:

  • 为成员变量提供 set get ⽅法;
  • 配置⽂件中进⾏配置;
1
2
3
4
5
6
7
8
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
<property name="userDAO">
<ref bean="userDAO"/>
</property>
</bean>
1234567

Spring4.x 废除了 <ref local=""/> 基本等效 <ref bean=""/>

Set注入的简化

基于属性的简化

JDK 类型注入:

1
2
3
4
<property name="id">
<value>10</value>
</property>
123

JDK类型注入简化:value 属性只能简化 8种基本类型 + String 注入标签;

1
2
<property name="id" value="10"/>
1

用户自定义类型注入:

1
2
3
4
5
6
7
8
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
<property name="userDAO">
<ref bean="userDAO"/>
</property>
</bean>
1234567

用户自定义类型注入简化:

1
2
3
4
5
6
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
12345

基于p命名空间的简化

JDK 类型注入:

1
2
3
4
5
6
7
8
9
<bean id="person" name="p" class="com.yusael.basic.Person">
<property name="id">
<value>10</value>
</property>
<property name="name">
<value>yusael</value>
</property>
</bean>
12345678

JDK 类型注入 - 基于p命名空间的简化。

1
2
3
<bean id="person" name="p" class="com.yusael.basic.Person" 
p:name="yusael" p:id="10"/>
12

用户自定义类型注入:

1
2
3
4
5
6
7
8
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl">
<property name="userDAO">
<ref bean="userDAO"/>
</property>
</bean>
1234567

用户自定义类型注入 - 基于p命名空间的简化。

1
2
3
4
5
<bean id="userDAO" class="com.yusael.dao.UserDAOImpl"></bean>

<bean id="userService" class="com.yusael.service.UserServiceImpl"
p:userDAO-ref="userDAO"/>
1234

构造注入

  • 注入:通过 Spring 的配置文件,为成员变量赋值;
  • Set注入:Spring 调用 Set 方法 通过 配置文件 为成员变量赋值;
  • 构造注入:Spring 调用 构造方法 通过 配置文件 为成员变量赋值;

构造注入开发

  • 提供有参构造方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Customer {
private String name;
private int age;

public Customer(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public String toString() {
return "Customer{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}

}
123456789101112131415161718
  • spring 配置文件
1
2
3
4
5
6
7
8
9
<bean id="customer" class="com.yusael.constructor.Customer">
<constructor-arg>
<value>zhenyu</value>
</constructor-arg>
<constructor-arg>
<value>21</value>
</constructor-arg>
</bean>
12345678

构造方法重载

参数个数不同

参数个数不同时,通过控制 <constructor-arg> 标签的数量进⾏区分;

如果只有一个参数的话,只需要一对 <constructor-arg> 标签:

1
2
3
4
5
6
<bean id="customer" class="com.yusael.constructor.Customer">
<constructor-arg>
<value>zhenyu</value>
</constructor-arg>
</bean>
12345

如果有两个参数的话,用两对 <constructor-arg> 标签,以此类推。

1
2
3
4
5
6
7
8
9
<bean id="customer" class="com.yusael.constructor.Customer">
<constructor-arg>
<value>zhenyu</value>
</constructor-arg>
<constructor-arg>
<value>22</value>
</constructor-arg>
</bean>
12345678

参数相同

构造参数个数相同时,通过在标签引入 type 属性 进⾏类型的区分 <constructor-arg type="">

1
2
3
4
5
6
<bean id="customer" class="com.yusael.constructor.Customer">
<constructor-arg type="int">
<value>20</value>
</constructor-arg>
</bean>
12345

注入总结

未来的实战中,应⽤ set注入 还是 构造注入

答:set 注入更多。

  1. 构造注入麻烦(重载)
  2. Spring 框架底层⼤量应⽤了 set注入。

在这里插入图片描述


学习资料:B站孙帅

-------------本文结束感谢您的阅读-------------