Spring注入详解
文章目录
1. 什么是注入
简单来讲,就是通过Spring工厂及配置⽂件,为所创建对象的成员变量赋值。而这个注入的方式又有很多种。接下来的文章会一一介绍。
通过编码的方式,为成员变量进行赋值,存在耦合,有了注入就可以很大程度上减少耦合。
2. 如何进行注入
- 为类的成员变量提供get、set方法
- 编写Spring的配置文件
<bean id="user" class="com.jc.bean.User">
<property name="id">
<value>1</value>
</property>
<property name="username">
<value>Tom</value>
</property>
</bean>
3. Set注入
Spring通过底层调用对象属性对应的set方法,完成成员变量的赋值,这种方式我们也称之为set注入。
针对于不同类型的成员变量,在<property>标签,需要嵌套其他标签
<property>
...
</property>
3.1 JDK内置类型
3.1.1 String+8种基本类型
<value>Tom</value>
<value>123</value>
<value>1.5</value>
...
3.1.2 数组
<list>
<value>Tom</value>
<value>Jerry</value>
<value>Rose</value>
</list>
3.1.3 Set集合
<set>
<value>111</value>
<value>222</value>
<value>333</value>
</set>
或是采用级联赋值的方式
<set>
<ref bean ...
</set>
3.1.4 List集合
<list>
<value>111</value>
<value>222</value>
</list>
<list>
<ref bean...
</list>
3.1.5 Map集合
注意: map -- entry -- key有特定的标签
<map>
<entry>
<key>
<value>Tom</value>
</key>
<value>123</value>
</entry>
<entry>
<key>
<value>Jerry</value>
</key>
<ref bean
</entry>
</map>
3.1.6 Properites
Properties类型特殊的Map key=String value=String
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
</props>
3.1.7 复杂的JDK类型
如日期类:Date
需要程序员自定义类型转换器,处理。
3.2 用户自定义类型
3.2.1 第一种方式
-
为类的成员变量提供set、get方法
-
配置文件中进行配置(赋值)
<bean id="userService" class="com.jc.service.impl.UserServiceImpl"> <property name="userDAO"> <bean id="userDAO" class="com.jc.dao.impl.UserDAOImpl"></bean> </property> </bean>
3.2.2 第二种方式
第一种方式存在一些问题:
- 配置文件代码冗余
- 被注入的对象(UserDAO),多次创建,浪费(JVM)内存资源
通过第二种方式可以进行优化:
-
同样需要提供set、get方法
-
在配置文件中进行配置
<bean id="userService" class="com.jc.service.impl.UserServiceImpl"> <property name="userDAO"> <ref bean="userDAO"/> </property> </bean> <bean id="userDAO" class="com.jc.dao.impl.UserDAOImpl"/>
3.3 Set注入简化写法
3.3.1 基于属性简化
JDK基本类型和String类型:
原版:
<property name="username">
<value>Tom</value>
</property>
简化后:
<property name="username" value="Tom"/>
注意:value
属性 只能简化8种基本类型+String 注入标签
用户自定义类型:
原版:
<bean id="userService" class="com.jc.service.impl.UserServiceImpl">
<property name="userDAO">
<ref bean="userDAO"/>
</property>
</bean>
<bean id="userDAO" class="com.jc.dao.impl.UserDAOImpl"/>
简化后:
<bean id="userService" class="com.jc.service.impl.UserServiceImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
<bean id="userDAO" class="com.jc.dao.impl.UserDAOImpl"/>
3.3.2 基于p命名空间简化
使用p命名空间需要现在文件头部引入p命名空间。
xmlns:p="http://www.springframework.org/schema/p"
JDK基本类型和String类型:
原版:
<bean id="user" class="com.jc.bean.User">
<property name="id">
<value>1</value>
</property>
<property name="username" value="Tom"/>
</bean>
简化后:
<bean id="user" class="com.jc.bean.User" p:id="1" p:username="Tom"/>
用户自定义类型:
原版:
<bean id="userService" class="com.jc.service.impl.UserServiceImpl">
<property name="userDAO" ref="userDAO"/>
</bean>
简化后:
<bean id="userService" class="com.jc.service.impl.UserServiceImpl" p:userDAO-ref="userDAO"/>
<bean id="userDAO" class="com.jc.dao.impl.UserDAOImpl"/>
4. 构造注入
Spring通过反射调用构造方法注入值
4.1 使用步骤
-
提供有参的构造方法
public class User { private int id; private String username; public User(int id, String username) { this.id = id; this.username = username; } }
-
编写Spring配置文件
<bean id="user" class="com.jc.bean.User"> <constructor-arg> <value>123</value> </constructor-arg> <constructor-arg> <value>Tom</value> </constructor-arg> </bean>
4.2 构造方法重载
4.2.1 参数个数不同时
通过控制<constructor-arg>标签的数量进⾏区分
4.2.2 构造参数个数相同时
通过在标签引⼊type属性 进⾏类型的区分 <constructor-arg type="xxx">
5. 注入总结
- 注入实际上就是Spring读取配置文件通过反射的方式创建对象的同时为对象内的属性赋值。
- 在实际开发过程中用set注入还是构造方法注入呢?
- 实际上是set注入使用的更多,原因有两点:
- 构造注入比较麻烦。
- Spring框架的底层也使用了大量的set注入。
- 实际上是set注入使用的更多,原因有两点: