Spring 高级注入技术
2025/9/17大约 7 分钟
Spring 高级注入技术
在前面的章节中,我们学习了Spring的基本依赖注入。本章将深入探讨Spring的高级注入技术,包括集合注入、特殊字符处理、命名空间注入和自动装配等重要功能。
前置知识
在学习本章内容前,请确保你已经掌握:
- Spring基础依赖注入(set注入、构造注入)
- Spring配置文件的基本语法
- Java集合框架的基本使用
集合类型注入
Spring支持注入各种集合类型,包括数组、List、Set、Map和Properties等。
数组注入
简单类型数组
查看完整代码示例
@Data
public class Student {
private String[] hobbies;
}
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="student" class="com.example.beans.Student">
<property name="hobbies">
<array>
<value>篮球</value>
<value>足球</value>
<value>游泳</value>
</array>
</property>
</bean>
</beans>
@Test
public void testArrayInjection() {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = context.getBean("student", Student.class);
System.out.println(Arrays.toString(student.getHobbies()));
}
对象类型数组
查看完整代码示例
@Data
public class Goods {
private String name;
}
@Data
public class Order {
private Goods[] goods;
}
<bean id="goods1" class="com.example.beans.Goods">
<property name="name" value="西瓜"/>
</bean>
<bean id="goods2" class="com.example.beans.Goods">
<property name="name" value="苹果"/>
</bean>
<bean id="order" class="com.example.beans.Order">
<property name="goods">
<array>
<!-- 对象类型使用ref标签 -->
<ref bean="goods1"/>
<ref bean="goods2"/>
</array>
</property>
</bean>
注意事项
- 简单类型数组使用
<value>
标签 - 对象类型数组使用
<ref>
标签
List集合注入
List集合是有序可重复的集合类型。
查看完整代码示例
@Data
public class People {
private List<String> names;
}
<bean id="peopleBean" class="com.example.beans.People">
<property name="names">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
<value>张三</value> <!-- List允许重复 -->
</list>
</property>
</bean>
Set集合注入
Set集合是无序不可重复的集合类型。
查看完整代码示例
@Data
public class People {
private Set<String> phones;
}
<bean id="peopleBean" class="com.example.beans.People">
<property name="phones">
<set>
<value>110</value>
<value>120</value>
<value>119</value>
<value>110</value> <!-- Set会自动去重 -->
</set>
</property>
</bean>
Map集合注入
Map集合用于存储键值对数据。
查看完整代码示例
@Data
public class People {
private Map<Integer, String> addresses;
}
<bean id="peopleBean" class="com.example.beans.People">
<property name="addresses">
<map>
<!-- key和value都是简单类型 -->
<entry key="1" value="北京大兴区"/>
<entry key="2" value="上海浦东区"/>
<entry key="3" value="深圳宝安区"/>
</map>
</property>
</bean>
Map注入规则
- 简单类型key使用
key
属性,对象类型key使用key-ref
属性 - 简单类型value使用
value
属性,对象类型value使用value-ref
属性
Properties注入
Properties是特殊的Map集合,键值都是String类型。
查看完整代码示例
@Data
public class DataSource {
private Properties properties;
}
<bean id="dataSource" class="com.example.beans.DataSource">
<property name="properties">
<props>
<prop key="driver">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
特殊值注入
null值和空字符串
注入空字符串
<!-- 方式一:使用value属性 -->
<property name="email" value=""/>
<!-- 方式二:使用value标签 -->
<property name="email">
<value/>
</property>
注入null值
<!-- 方式一:不设置属性值 -->
<bean id="vipBean" class="com.example.beans.Vip"/>
<!-- 方式二:使用null标签 -->
<property name="email">
<null/>
</property>
特殊字符处理
XML中有5个特殊字符:<
、>
、'
、"
、&
,需要特殊处理。
使用转义字符
特殊字符 | 转义字符 |
---|---|
< | < |
> | > |
' | ' |
" | " |
& | & |
<property name="result" value="2 < 3"/>
使用CDATA区
查看CDATA使用示例
<property name="result">
<!-- CDATA区中的内容不会被XML解析器解析 -->
<value><![CDATA[2 < 3 && x > y]]></value>
</property>
注意
使用CDATA时,只能使用 <value>
标签,不能使用 value
属性。
命名空间注入
p命名空间注入
p命名空间是对set注入的简化。
配置要求
- 在XML头部添加p命名空间:
xmlns:p="http://www.springframework.org/schema/p"
- 提供对应的setter方法
查看p命名空间示例
@Data
public class Customer {
private String name;
private int age;
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 使用p命名空间简化配置 -->
<bean id="customer" class="com.example.beans.Customer"
p:name="张三" p:age="25"/>
</beans>
c命名空间注入
c命名空间是对构造方法注入的简化。
配置要求
- 在XML头部添加c命名空间:
xmlns:c="http://www.springframework.org/schema/c"
- 提供对应的构造方法
查看c命名空间示例
@Data
@AllArgsConstructor
public class MyTime {
private int year;
private int month;
private int day;
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 方式一:使用参数名 -->
<bean id="myTime1" class="com.example.beans.MyTime"
c:year="2024" c:month="12" c:day="25"/>
<!-- 方式二:使用参数索引 -->
<bean id="myTime2" class="com.example.beans.MyTime"
c:_0="2024" c:_1="12" c:_2="25"/>
</beans>
util命名空间
util命名空间用于配置复用,避免重复配置。
查看util命名空间示例
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 定义可复用的Properties配置 -->
<util:properties id="dbConfig">
<prop key="driver">com.mysql.cj.jdbc.Driver</prop>
<prop key="url">jdbc:mysql://localhost:3306/spring</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</util:properties>
<!-- 多个Bean可以复用同一个配置 -->
<bean id="dataSource1" class="com.example.beans.MyDataSource">
<property name="properties" ref="dbConfig"/>
</bean>
<bean id="dataSource2" class="com.example.beans.MyDataSource">
<property name="properties" ref="dbConfig"/>
</bean>
</beans>
自动装配
Spring提供了自动装配功能,可以根据名称或类型自动注入依赖。
根据名称自动装配(byName)
查看byName自动装配示例
@Data
public class UserDao {
public void insert() {
System.out.println("正在保存用户数据");
}
}
@Data
public class UserService {
private UserDao userDao; // 属性名要与Bean的id匹配
public void save() {
userDao.insert();
}
}
<bean id="userService" class="com.example.service.UserService"
autowire="byName"/>
<!-- Bean的id必须与UserService中的属性名一致 -->
<bean id="userDao" class="com.example.dao.UserDao"/>
byName装配原理
- Spring会根据setter方法名确定属性名
- 例如:
setUserDao()
对应属性名userDao
- 然后查找id为
userDao
的Bean进行注入
根据类型自动装配(byType)
查看byType自动装配示例
@Data
public class AccountDao {
public void insert() {
System.out.println("正在保存账户信息");
}
}
@Data
public class AccountService {
private AccountDao accountDao;
public void save() {
accountDao.insert();
}
}
<bean id="accountService" class="com.example.service.AccountService"
autowire="byType"/>
<!-- 根据类型匹配,id可以任意 -->
<bean class="com.example.dao.AccountDao"/>
byType装配限制
- 配置文件中同一类型的Bean必须唯一
- 如果存在多个相同类型的Bean,会抛出异常
- 仍然需要提供setter方法
最佳实践
选择合适的注入方式
- 简单配置:使用p命名空间或c命名空间
- 复杂集合:使用标准的XML配置
- 配置复用:使用util命名空间
- 自动装配:在依赖关系明确且唯一时使用
代码优化建议
// 推荐:使用Lombok简化代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private Integer age;
private List<String> hobbies;
private Map<String, String> properties;
}
配置文件组织
<!-- 建议按功能模块组织配置 -->
<!-- 1. 公共配置 -->
<util:properties id="commonConfig">
<!-- 公共属性 -->
</util:properties>
<!-- 2. DAO层配置 -->
<bean id="userDao" class="com.example.dao.UserDao"/>
<!-- 3. Service层配置 -->
<bean id="userService" class="com.example.service.UserService"
autowire="byType"/>
总结
本章我们学习了Spring的高级注入技术:
- 集合注入:支持数组、List、Set、Map、Properties等集合类型
- 特殊值处理:null值、空字符串和特殊字符的处理方法
- 命名空间注入:p、c、util命名空间简化配置
- 自动装配:byName和byType两种自动装配方式
这些技术让我们能够更灵活地配置Spring应用,提高开发效率。在实际项目中,建议根据具体场景选择合适的注入方式,并结合Lombok等工具简化代码。
下一步学习
接下来我们将学习Spring的Bean作用域和生命周期管理。