四、Spring对IoC的实现
4.1 IoC 控制反转
概念理解
- 控制反转(Inversion of Control)是一种设计思想
- 核心目的:降低程序耦合度,提高扩展性
- 遵循原则:OCP(开闭原则)、DIP(依赖倒置原则)
反转内容
- 对象创建权:由程序员 → 交给容器管理
- 对象关系维护权:由硬编码 → 交给容器管理
实现方式
- DI(Dependency Injection):依赖注入
- 容器通过注入方式管理对象依赖关系
优势对比
传统方式 | IoC方式 |
---|---|
对象创建耦合度高 | 对象创建由容器管理 |
修改依赖需要改代码 | 只需修改配置 |
难以扩展 | 易于扩展 |
4.2 依赖注入
核心概念
依赖注入(Dependency Injection)是IoC的具体实现方式:
- 实现思想:由容器动态地将依赖关系注入到组件中
- 管理范围:Bean的创建和属性赋值(关系维护)
专业术语解释
术语 | 含义 |
---|---|
Bean管理 | 包括Bean的创建和依赖关系维护 |
依赖 | 对象之间的关联关系 |
注入 | 容器传递依赖关系的行为 |
实现方式对比
主要实现方式:
- set注入:通过set方法注入依赖
- 构造注入:通过构造方法注入依赖
4.2.1 set注入
set注入,基于set方法实现的,底层会通过反射机制调用属性对应的set方法然后给属性赋值。这种方式要求属性必须对外提供set方法。
下面是一个set注入的示例代码:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.powernode</groupId><artifactId>spring6-003-dependency-injection</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>6.2.5</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.19.0</version></dependency><dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-slf4j2-impl</artifactId><version>2.19.0</version></dependency></dependencies><properties><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties></project>
[代码说明:这是一个Maven项目的pom.xml配置文件,包含了Spring和JUnit的依赖]
// UserDao.java
public class UserDao {public void insert(){System.out.println("正在保存用户数据。");}
}// UserService.java
public class UserService {private UserDao userDao;// 使用set方式注入,必须提供set方法public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
[代码说明:这是一个典型的DAO和Service层的代码示例,展示了如何使用set注入]
<?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="userDaoBean" class="com.powernode.spring6.dao.UserDao"/><bean id="userServiceBean" class="com.powernode.spring6.service.UserService"><property name="userDao" ref="userDaoBean"/></bean>
</beans>
[代码说明:这是Spring的配置文件,展示了如何配置bean和它们之间的依赖关系]
测试代码及运行结果:
@Test
public void testSetDI(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");UserService userService = applicationContext.getBean("userServiceBean", UserService.class);userService.save();
}
运行结果:
正在保存用户数据。
set注入的实现原理
set注入的核心实现原理是通过XML配置中的property标签来完成的:
<bean id="userServiceBean" class="com.powernode.spring6.service.UserService"><property name="userDao" ref="userDaoBean"/>
</bean>
实现原理说明:
- 通过property标签获取属性名:userDao
- 通过属性名推断出set方法名:setUserDao
- 通过反射机制调用setUserDao()方法给属性赋值
- property标签的name是属性名
- property标签的ref是要注入的bean对象的id
重要说明:
- property标签通过ref属性来完成bean的装配,这是bean最简单的一种装配方式
- 装配指的是:创建系统组件之间关联的动作
- set方法是必须的,如果没有set方法会报错
- 如果一个属性名是userDao,那么对应的set方法必须是setUserDao()
测试验证:如果去掉set方法,会出现以下错误:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceBean':
No property 'userDao' found on class 'com.powernode.spring6.service.UserService'
4.2.2 构造注入
核心原理:通过调用构造方法来给属性赋值。下面是一个构造注入的示例:
public class OrderDao {public void deleteById(){System.out.println("正在删除订单。。。");}
}public class OrderService {private OrderDao orderDao;// 通过反射机制调用构造方法给属性赋值public OrderService(OrderDao orderDao) {this.orderDao = orderDao;}public void delete(){orderDao.deleteById();}
}
对应的Spring配置文件:
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService"><!--index="0"表示构造方法的第一个参数,将orderDaoBean对象传递给构造方法的第一个参数。--><constructor-arg index="0" ref="orderDaoBean"/>
</bean>
测试代码:
@Test
public void testConstructorDI(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");OrderService orderServiceBean = applicationContext.getBean("orderServiceBean", OrderService.class);orderServiceBean.delete();
}
运行结果:
正在删除订单。。。
构造注入的多参数情况
当构造方法有多个参数时,有以下几种配置方式:
- 使用参数下标
package com.powernode.spring6.service;import com.powernode.spring6.dao.UserDao;
import com.powernode.spring6.dao.VipDao;public class ConstructorService {private UserDao userDao;private VipDao vipDao;public ConstructorService() {}public ConstructorService(UserDao userDao, VipDao vipDao) {this.userDao = userDao;this.vipDao = vipDao;}public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void setVipDao(VipDao vipDao) {this.vipDao = vipDao;}public void save() {userDao.info();vipDao.info();}
}
配置文件:
<bean id="orderDaoBean" class="com.powernode.spring6.dao.OrderDao"/>
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService"><!--第一个参数下标是0--><constructor-arg index="0" ref="vipDaoBean"/><!--第二个参数下标是1--><constructor-arg index="1" ref="userDaoBean"/>
</bean>
<bean id="userDaoBean" class="com.powernode.spring6.dao.UserDao"/>
<bean id="vipDaoBean" class="com.powernode.spring6.dao.VipDao"/>
- 使用参数名
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService"><constructor-arg name="vipDao" ref="vipDaoBean"/><constructor-arg name="userDao" ref="userDaoBean"/>
</bean>
- 省略参数下标和名称(通过类型自动推断)
<bean id="orderServiceBean" class="com.powernode.spring6.service.OrderService"><constructor-arg ref="vipDaoBean"/><constructor-arg ref="userDaoBean"/>
</bean>
注意事项:
- Spring在装配方面做得比较健壮,支持多种方式的参数匹配
- 可以通过下标
- 可以通过参数名
- 也可以不指定下标和参数名,让Spring通过类型自动推断
- 当有多个相同类型的参数时,建议使用下标或参数名来明确指定
4.3 set注入专题
4.3.1 注入外部Bean
这是最常用的注入方式,bean定义在外部,在property标签中使用ref属性进行注入。示例如下:
<?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="userDaoBean" class="com.powernode.spring6.dao.UserDao"/><bean id="userServiceBean" class="com.powernode.spring6.service.UserService"><property name="userDao" ref="userDaoBean"/></bean></beans>
4.3.2 注入内部Bean
内部Bean的方式是在bean标签中嵌套bean标签。这种方式作为了解,实际开发中较少使用。示例如下:
<?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="userServiceBean" class="com.powernode.spring6.service.UserService"><property name="userDao"><bean class="com.powernode.spring6.dao.UserDao"/></property></bean>
</beans>
测试代码:
@Test
public void testInnerBean(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-inner-bean.xml");UserService userService = applicationContext.getBean("userServiceBean", UserService.class);userService.save();
}
4.3.3 注入简单类型
在Spring中,简单类型包括:
- 基本数据类型
- 基本数据类型对应的包装类
- String或其他的CharSequence子类
- Number子类
- Date子类
- Enum子类
- URI
- URL
- Temporal子类
- Locale
- Class
- 以上类型对应的数组
示例代码:
package com.powernode.spring6.bean;public class SimpleValueType {/** public static boolean isSimpleValueType(Class<?> type) {return !isVoidType(type) && (isPrimitiveOrWrapper(type) ||* Enum.class.isAssignableFrom(type) ||* CharSequence.class.isAssignableFrom(type) ||* Number.class.isAssignableFrom(type) ||* Date.class.isAssignableFrom(type) ||* Temporal.class.isAssignableFrom(type) ||* ZoneId.class.isAssignableFrom(type) ||* TimeZone.class.isAssignableFrom(type) ||* File.class.isAssignableFrom(type) ||* Path.class.isAssignableFrom(type) ||* Charset.class.isAssignableFrom(type) ||* Currency.class.isAssignableFrom(type) ||* InetAddress.class.isAssignableFrom(type) ||* URI.class == type || URL.class == type ||* UUID.class == type ||* Locale.class == type ||* Pattern.class == type ||* Class.class == type);} */private int age;private Integer age2;private boolean flag;private Boolean flag2;private char c;private Character c2;private String userName;private Season season;private Class clazz;@Overridepublic String toString() {return "SimpleValueType{" +"age=" + age +", age2=" + age2 +", flag=" + flag +", flag2=" + flag2 +", c=" + c +", c2=" + c2 +", userName='" + userName + '\'' +", season=" + season +", clazz=" + clazz +'}';}public void setClazz(Class clazz) {this.clazz = clazz;}public void setAge(int age) {this.age = age;}public void setAge2(Integer age2) {this.age2 = age2;}public void setFlag(boolean flag) {this.flag = flag;}public void setFlag2(Boolean flag2) {this.flag2 = flag2;}public void setC(char c) {this.c = c;}public void setC2(Character c2) {this.c2 = c2;}public void setUserName(String userName) {this.userName = userName;}public void setSeason(Season season) {this.season = season;}
}
配置文件:
<?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="svt" class="com.powernode.spring6.bean.SimpleValueType"><property name="userName" value="张三"/><property name="age" value="18"/><property name="age2" value="20"/><property name="flag" value="true"/><property name="flag2" value="false"/><property name="c" value="男"/><property name="c2" value="女"/><property name="season" value="SPRING"/><property name="clazz" value="java.lang.String"/><!--报错了,说1970-10-11这个字符串无法转换成java.util.Date类型。--><!--<property name="birth" value="1970-10-11"/>--><!--如果你硬要把Date当做简单类型的话,使用value赋值的话,这个日期字符串格式有要求--><!--在实际开发中,我们一般不会把Date当做简单类型,虽然它是简单类型。一般会采用ref给Date类型的属性赋值。--></bean>
</beans>
测试代码:
@Testpublic void testSimpleTypeSet2() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("set-di.xml");SimpleValueType svt = applicationContext.getBean("svt", SimpleValueType.class);System.out.println(svt);}
运行结果:
SimpleValueType{age=18, age2=20, flag=true, flag2=false, c=男, c2=女, userName='张三', season=SPRING, clazz=class java.lang.String}
注意:如果给简单类型赋值,使用value属性,而不是ref属性。
4.3.11 注入特殊字符
在XML中有5个特殊字符需要特殊处理:
-
< 小于号
-
大于号
-
’ 单引号
-
" 双引号
-
& 和号
这些字符在XML中会被特殊对待,会被当做XML语法的一部分进行解析。如果这些特殊符号直接出现在注入的字符串当中,会报错。
解决方案有两种:
- 使用转义字符
特殊字符对应的转义字符:
特殊字符 | 转义字符 |
---|---|
> | > |
< | < |
’ | ' |
" | " |
& | & |
示例代码:
public class Math {private String result;public void setResult(String result) {this.result = result;}@Overridepublic String toString() {return "Math{" +"result='" + result + '\'' +'}';}
}
配置文件:
<bean id="mathBean" class="com.powernode.spring6.beans.Math"><property name="result" value="2 < 3"/>
</bean>
- 使用CDATA区
CDATA区中的数据会被XML解析器忽略。格式:<![CDATA[内容]]>
<bean id="mathBean" class="com.powernode.spring6.beans.Math"><property name="result"><value><![CDATA[2 < 3]]></value></property>
</bean>
测试代码:
@Test
public void testSpecial(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-special.xml");Math mathBean = applicationContext.getBean("mathBean", Math.class);System.out.println(mathBean);
}
运行结果:
Math{result='2 < 3'}
注意:使用CDATA时,不能使用value属性,只能使用value标签。
4.4 p命名空间注入
p命名空间注入是为了简化配置而引入的。使用p命名空间注入有两个前提条件:
- 在XML头部信息中添加p命名空间的配置信息:
xmlns:p="http://www.springframework.org/schema/p"
- p命名空间注入是基于setter方法的,所以需要对应的属性提供setter方法
示例代码:
public class Customer {private String name;private int age;public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Customer{" +"name='" + name + '\'' +", age=" + 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"><bean id="customerBean" class="com.powernode.spring6.beans.Customer" p:name="zhangsan" p:age="20"/></beans>
4.5 c命名空间注入
c命名空间是简化构造方法注入的。使用c命名空间的两个前提条件:
- 需要在xml配置文件头部添加信息:
xmlns:c="http://www.springframework.org/schema/c"
- 需要提供构造方法
示例代码:
public class MyTime {private int year;private int month;private int day;public MyTime(int year, int month, int day) {this.year = year;this.month = month;this.day = day;}@Overridepublic String toString() {return "MyTime{" +"year=" + year +", month=" + month +", day=" + 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="myTimeBean" class="com.powernode.spring6.beans.MyTime" c:year="1970" c:month="1" c:day="1"/><!--第二种方式:通过参数索引注入--><bean id="myTimeBean2" class="com.powernode.spring6.beans.MyTime" c:_0="2008" c:_1="8" c:_2="8"/></beans>
4.6 util命名空间
util命名空间可以让配置复用。使用util命名空间的前提是在spring配置文件头部添加配置信息:
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">
示例代码:
public class MyDataSource1 {private Properties properties;public void setProperties(Properties properties) {this.properties = properties;}@Overridepublic String toString() {return "MyDataSource1{" +"properties=" + properties +'}';}
}public class MyDataSource2 {private Properties properties;public void setProperties(Properties properties) {this.properties = properties;}@Overridepublic String toString() {return "MyDataSource2{" +"properties=" + properties +'}';}
}
配置文件:
<?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.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"><!--定义一个Properties配置--><util:properties id="prop"><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都引用相同的Properties配置--><bean id="dataSource1" class="com.powernode.spring6.beans.MyDataSource1"><property name="properties" ref="prop"/></bean><bean id="dataSource2" class="com.powernode.spring6.beans.MyDataSource2"><property name="properties" ref="prop"/></bean>
</beans>
4.7 基于XML的自动装配
Spring可以完成自动化的注入,自动化注入又被称为自动装配。它可以根据名字进行自动装配,也可以根据类型进行自动装配。
4.7.1 根据名称自动装配
示例代码:
public class UserDao {public void insert(){System.out.println("正在保存用户数据。");}
}public class UserService {private UserDao userDao;// 这个set方法非常关键public void setUserDao(UserDao userDao) {this.userDao = userDao;}public void save(){userDao.insert();}
}
配置文件:
<?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="userService" class="com.powernode.spring6.service.UserService" autowire="byName"/><bean id="userDao" class="com.powernode.spring6.dao.UserDao"/></beans>
要点说明:
- 使用autowire="byName"属性开启按名称自动装配
- 底层会调用set方法进行注入
- 根据set方法名推断属性名,例如setUserDao()方法对应属性名userDao
- 自动匹配与属性名相同的bean的id注入
4.7.2 根据类型自动装配
示例代码:
public class AccountDao {public void insert(){System.out.println("正在保存账户信息");}
}public class AccountService {private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}public void save(){accountDao.insert();}
}
配置文件:
<?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"><!--byType表示根据类型自动装配--><bean id="accountService" class="com.powernode.spring6.service.AccountService" autowire="byType"/><bean class="com.powernode.spring6.dao.AccountDao"/></beans>
要点说明:
- 使用autowire="byType"属性开启按类型自动装配
- 根据属性类型到Spring容器中查找对应类型的bean注入
- 如果同类型的bean在Spring容器中不是唯一的,则会报错
- 按类型装配时,bean的id可以任意,但是类型必须匹配
4.8 Spring引入外部属性配置文件
在实际开发中,数据源的配置信息(如driver、url、username、password等)通常会放到单独的属性文件中,这样便于修改和维护。Spring提供了在XML中引入外部属性文件的功能。
示例代码:
public class MyDataSource implements DataSource {private String driver;private String url;private String username;private String password;// setter方法和toString方法省略...@Overridepublic String toString() {return "MyDataSource{" +"driver='" + driver + '\'' +", url='" + url + '\'' +", username='" + username + '\'' +", password='" + password + '\'' +'}';}
}
属性文件jdbc.properties:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/spring
username=root
password=root123
Spring配置文件:
<?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:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--引入外部属性文件--><context:property-placeholder location="jdbc.properties"/><bean id="dataSource" class="com.powernode.spring6.beans.MyDataSource"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></bean>
</beans>
要点说明:
- 使用context命名空间引入外部属性文件
- 使用${属性名}的方式引用属性值
- 这种方式可以将配置信息从Spring配置文件中解耦出来
4.9 集合注入
Spring支持对集合类型进行注入,包括List、Set、Map和Properties等。
4.9.1 注入List集合
示例代码:
public class Person {private List<String> names;public void setNames(List<String> names) {this.names = names;}@Overridepublic String toString() {return "Person{" +"names=" + names +'}';}
}
配置文件:
<bean id="personBean" class="com.powernode.spring6.beans.Person"><property name="names"><list><value>张三</value><value>李四</value><value>王五</value></list></property>
</bean>
4.9.2 注入Set集合
示例代码:
public class Person {private Set<String> addresses;public void setAddresses(Set<String> addresses) {this.addresses = addresses;}@Overridepublic String toString() {return "Person{" +"addresses=" + addresses +'}';}
}
配置文件:
<bean id="personBean" class="com.powernode.spring6.beans.Person"><property name="addresses"><set><value>北京</value><value>上海</value><value>广州</value></set></property>
</bean>
4.9.3 注入Map集合
示例代码:
public class Person {private Map<String, String> phones;public void setPhones(Map<String, String> phones) {this.phones = phones;}@Overridepublic String toString() {return "Person{" +"phones=" + phones +'}';}
}
配置文件:
<bean id="personBean" class="com.powernode.spring6.beans.Person"><property name="phones"><map><!--如果key和value不是简单类型就用这个配置。--><!--<entry key-ref="" value-ref=""/>--><!--如果是简单类型就是key和value--><entry key="home" value="010-12345678"/><entry key="mobile" value="13800138000"/></map></property>
</bean>
4.9.4 注入Properties
示例代码:
public class Person {private Properties properties;public void setProperties(Properties properties) {this.properties = properties;}@Overridepublic String toString() {return "Person{" +"properties=" + properties +'}';}
}
配置文件:
<bean id="personBean" class="com.powernode.spring6.beans.Person"><property name="properties"><props><prop key="username">admin</prop><prop key="password">123456</prop></props></property>
</bean>
4.10 注入null和空字符串
4.10.1 注入null
示例代码:
public class Cat {private String name;public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Cat{" +"name='" + name + '\'' +'}';}
}
配置文件:
<bean id="catBean" class="com.powernode.spring6.beans.Cat"><property name="name"><!--不给属性注入,属性的默认值就是null--><!--<property name="name" value="tom"></property>--><!-- 这不是注入null,这只是注入了一个"null"字符串--><!--<property name="name" value="null"/>--><!--这种方式是手动注入null--><null/></property>
</bean>
4.10.2 注入空字符串
配置文件:
<bean id="catBean" class="com.powernode.spring6.beans.Cat"><!--注入空字符串第一种方式--><!--<property name="name" value=""/>--><!--注入空字符串第二种方式--><property name="name"><value/></property>
</bean>
4.11 注入数组
示例代码:
public class Person {private String[] hobbies;public void setHobbies(String[] hobbies) {this.hobbies = hobbies;}@Overridepublic String toString() {return "Person{" +"hobbies=" + Arrays.toString(hobbies) +'}';}
}
配置文件:
<bean id="personBean" class="com.powernode.spring6.beans.Person"><property name="hobbies"><array><value>唱歌</value><value>跳舞</value><value>编程</value></array></property>
</bean>