关于 idref 的用途,目前,我也不怎么用,只是在 Spring 示例中有这样的一个标签,带着好奇心 ,我测试分析一下这和块的源码。
Boss.java
@Data public class Boss { private String carId; }
Car.java
@Data public class Car { private Long id ; private String brand; private int maxSpeed; }
spring29_reference.xml
<?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:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="car" class="com.spring_1_100.test_21_30.test29_reference.Car"> </bean> <bean id="boss1" class="com.spring_1_100.test_21_30.test29_reference.Boss" p:carId="car1"></bean> <!-- idref元素用来将容器内其它bean的id传给<constructor-arg/> 或 <property/>元素,同时提供错误验证功能。 如果 bean value 写成 car1 将出现如下错误 BeanDefinitionStoreException: Invalid bean name 'car1' in bean reference for bean property 'carId' --> <bean id="boss2" class="com.spring_1_100.test_21_30.test29_reference.Boss"> <property name="carId"> <idref bean="carxx"></idref> </property> </bean> </beans>
测试
public class Test29 { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:spring_1_100/config_21_30/spring29_reference.xml"); } }
结果输出:
源码解析:
首先,我们对于 idref 的 beanDefinition 解析
/** * Return a typed String value Object for the given 'idref' element. */ public Object parseIdRefElement(Element ele) { // A generic reference to any name of any bean. String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); if (!StringUtils.hasLength(refName)) { // A reference to the id of another bean in the same XML file. refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE); if (!StringUtils.hasLength(refName)) { error("Either 'bean' or 'local' is required for element", ele); return null; } } if (!StringUtils.hasText(refName)) { error(" element contains empty target attribute", ele); return null; } RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName); ref.setSource(extractSource(ele)); return ref; }
获取到 bean,并以 RuntimeBeanNameReference对象保存到propertyValueList集合中。
在填充属性的解析属性过程中,先调用容器中是不是存在该 bean,如果存在,则返回 refName,如果不存在,则抛出异常。
因此,代码将抛出引用不存在异常。因此,idref 标签,只是多了一个属性的检测过程。具体情况,要看公司业务,才来使用了。
本例的 gitHub 地址是
https://github.com/quyixiao/spring_tiny/tree/master/src/main/java/com/spring_1_100/test_21_30/test29_reference