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内置类型
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
|
1 2 3 4 5 6 7 8
| <property name="tels"> <set> <value>138xxxxxxxxxx</value> <value>139xxxxxxxxxx</value> <value>138xxxxxxxxxx</value> </set> </property> 1234567
|
1 2 3 4 5 6 7 8
| <property name="addresses"> <list> <value>China</value> <value>Earth</value> <value>hell</value> </list> </property> 1234567
|
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
|
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
|
需要程序员⾃定义类型转换器,处理。
用户自定义类型
第一种方式
[开发步骤]:
- 为成员变量提供 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
|
第二种方式
第⼀种赋值⽅式存在的问题:
- 配置⽂件代码冗余;
- 被注入的对象 (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
|
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 注入更多。
- 构造注入麻烦(重载)
- Spring 框架底层⼤量应⽤了 set注入。
学习资料:B站孙帅