在Spring框架中,<constructor-arg>元素用于通过构造函数注入来给bean的属性赋值。当Spring容器创建这个bean的实例时,它会使用这些<constructor-arg>元素指定的参数来调用bean的构造函数。
以下是Spring如何处理<constructor-arg>元素的:
1. 解析参数值: 对于value属性,Spring会直接使用指定的值。对于ref属性,Spring会查找容器中ID或名称与指定值相匹配的bean,并使用该bean的实例。
2. 确定构造函数: Spring会查找bean类中的构造函数,该构造函数的参数类型和数量必须与<constructor-arg>元素指定的参数类型和数量相匹配。如果找到多个匹配的构造函数,Spring会使用type属性或参数的顺序来确定要使用的构造函数。
3. 创建bean实例: Spring使用确定的构造函数和解析的参数值来创建bean的新实例。
例如,假设你有一个类Book,它有一个接受四个参数的构造函数:
public class Book {
public Book(int id, String name, double price, Date date) {
// ...
}
}
你可以使用以下XML配置来创建Book的实例:
<bean id="book" class="com.example.Book">
<constructor-arg name="id" value="1"/>
<constructor-arg name="name" value="西游记"/>
<constructor-arg name="price" value="1000"/>
<constructor-arg name="date" ref="date"/>
</bean>
<bean id="date" class="java.util.Date"/>
在Spring的XML配置文件中,<property>元素的value属性默认是字符串类型。所以在你给出的例子中,value的值"1","真三国"和"40"都是字符串。
然而,Spring框架在注入这些属性值到对应的bean时,会尝试进行类型转换。具体的转换规则取决于bean的属性类型。例如,如果bean的id属性是int类型,那么Spring会尝试将字符串"1"转换为整数1。同样,如果price属性是double类型,那么Spring会尝试将字符串"40"转换为浮点数40.0。
如果类型转换失败,例如尝试将字符串"真三国"转换为整数,那么Spring会抛出一个异常。
所以,虽然value属性的值在XML文件中是字符串,但是在实际的bean中,它们可能会被转换为其他类型
在这个例子中,当Spring创建book的实例时,它会使用Book类的构造函数,参数值分别为1,"西游记",1000和date bean的实例。
在Spring框架中,<property>元素用于通过setter方法注入来给bean的属性赋值。当Spring容器创建这个bean的实例时,它会使用这些<property>元素指定的值来调用bean的setter方法。
以下是Spring如何处理<property>元素的:
1. 解析属性值: 对于value属性,Spring会直接使用指定的值。对于ref属性,Spring会查找容器中ID或名称与指定值相匹配的bean,并使用该bean的实例。
2. 确定setter方法: Spring会查找bean类中的setter方法,该方法的名称必须与<property>元素的name属性相匹配(例如,对于name="id",Spring会查找setId()方法)。
3. 调用setter方法: Spring使用确定的setter方法和解析的属性值来设置bean的属性。
例如,假设你有一个类Book,它有四个setter方法:
public class Book {
public void setId(int id) {
// ...
}
public void setName(String name) {
// ...
}
public void setPrice(double price) {
// ...
}
public void setDate(Date date) {
// ...
}
}
你可以使用以下XML配置来设置Book的属性:
<bean id="book" class="com.example.Book">
<property name="id" value="2"/>
<property name="name" value="红楼梦"/>
<property name="price" value="2000"/>
<property name="date" ref="date"/>
</bean>
<bean id="date" class="java.util.Date"/>
在这个例子中,当Spring创建book的实例时,它会调用setId(2),setName("红楼梦"),setPrice(2000)和setDate(date)方法来设置book的属性,其中date是另一个bean的实例。
<property name="set">
<set>
<value>苍</value>
<bean id="book2" class="com.qf.pojo.Book"/>
<ref bean="date"/>
</set>
</property>
这里的底层实现原理主要涉及到Spring框架的IoC(控制反转)和DI(依赖注入)。
1. 控制反转(IoC):Spring框架创建并管理对象的生命周期,而不是由程序员手动创建。这就是所谓的"控制反转",控制权从程序员转移到了Spring框架。
2. 依赖注入(DI):Spring框架通过XML配置文件或注解,将依赖关系注入到对象中。在这个例子中,"book2" bean和"date" bean被注入到"set"属性中。
在Spring框架中,当解析XML配置文件并遇到<set>元素时,Spring会创建一个新的Set集合。然后,它会解析<set>元素内部的子元素,将这些元素(在这个例子中是一个字符串值,一个bean实例,和一个bean引用)添加到新创建的Set集合中。
然后,Spring会调用对应bean的set方法(这是一个JavaBean的标准setter方法),并将新创建的Set集合作为参数传入。这就是所谓的依赖注入(DI):Spring框架负责创建和配置对象,然后将这些对象注入到其他对象中。
这个过程可以用以下的Java伪代码来表示:
Set set = new HashSet();
set.add("苍");
set.add(new Book()); // 假设Book是一个无参数的构造函数
set.add(getBean("date")); // 假设getBean是一个方法,用于根据id获取bean
bean.setSet(set); // 假设bean是需要设置属性的对象
这段伪代码并不完全准确,因为在实际的Spring框架中,创建和配置bean的过程要复杂得多,包括处理构造函数参数,处理属性值,处理bean的生命周期等等。但是,它应该能够给你一个大致的理解。