【问题标题】:Spring IDREF usageSpring IDREF 使用
【发布时间】:2013-01-30 15:07:34
【问题描述】:

我有一个 spring.xml 定义如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<bean id="triangle" class="org.tutorial.spring.Triangle">
    <property name="pointA">
        <idref bean="pointA"/>
    </property>
    <property name="pointB" ref="pointB"/>
    <property name="pointC" ref="pointC"/>
</bean>
<bean id="pointA" class="org.tutorial.spring.Point">
    <property name="x" value="0"/>
    <property name="y" value="0"/>
</bean>
<bean id="pointB" class="org.tutorial.spring.Point">
    <property name="x" value="100"/>
    <property name="y" value="200"/>
</bean>
<bean id="pointC" class="org.tutorial.spring.Point">
    <property name="x" value="-100"/>
    <property name="y" value="-200"/>
</bean>
</beans>

Point 类基本上是一个有 2 个私有 int 成员的类。我的问题是我在 IDREF 上收到如下错误:

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'org.tutorial.spring.Point' for property 'pointA'; 
nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [org.tutorial.spring.Point] for property 'pointA': no matching editors or conversion strategy found

据我了解,bean PointA 的 IDREF(在上述情况下)的目的是 bean 三角形存在(错误检查)。所以我确实在 IDREF 元素中提供了 bean PointA(string) 的名称。为什么我会收到上述错误?

当我认为它只是通过提供其名称来检查 bean (PointA) 的存在时,为什么它试图将字符串转换为 Point?

我真的很困惑。请帮忙。谢谢。

【问题讨论】:

标签: spring


【解决方案1】:

idref用于传递一个bean(即String)的名称(标识符)

&lt;idref bean="pointA"&gt; 与字符串值pointA 完全相同,只是如果没有定义这样的 bean,Spring 会报错。

详情请见the Spring documentation

要传递实际的 bean,只需使用 ref,就像使用 pointBpointC 一样。

【讨论】:

  • 在问题中,有一个 id 为“pointA”的 bean,它被三角形引用,为什么会出现异常?
  • @GauravKumar 因为字符串 "pointA" 只是一个字符串 - 而不是标识符为 pointA 的 Point bean。
  • idref 正如你所说,用于传递 bean 的名称(标识符)。这正是所讨论的。 这条语句的意思是,在 bean "triangle" 的属性 "pointA" 中注入一个 id 为 "pointA" 的 bean。正如我们在问题中看到的那样,我们确实定义了一个 id 为“pointA”的 bean。所以我认为这个例外不应该出现。我不明白发生此异常的原因。如果这个 bean 没有被定义,那么它是可以理解的
  • 不。再次重申:&lt;property name="foo"&gt;&lt;idref bean="bar"/&gt;&lt;/property&gt;&lt;property name="foo" ref="bar"/&gt; 完全相同。与&lt;property name="foo" value="bar"/&gt; 相同,只是在没有名为“bar”的bean 时会失败。真的,这一切都在文档中。
  • 那么idref 是干什么用的?使用它的目的是什么?看到这个词我有点搞砸了。
【解决方案2】:

idref 元素只是将容器中另一个 bean 的 id(字符串值 - 不是引用)传递给 or 元素的一种防错方法。

简单来说,idref 元素用于传递字符串值,使用 idref 标记允许容器在部署时验证所引用的命名 bean 是否实际存在。

考虑下面的例子

当我们调用 secondBean.getSecondMessage() 时,请注意控制台中的输出,该值是使用 idref 属性设置的 firstBean。

注意: 元素带来价值的常见地方是在 ProxyFactoryBean bean 定义中的 AOP 拦截器配置中。在指定拦截器名称时使用元素可防止您拼错拦截器 ID。

【讨论】:

    【解决方案3】:

    通过使用“idref”标签,您可以在部署时验证所引用的命名 bean 是否实际存在。

    例如,

    <bean id="paulo" class="com.sample.pojo.Author">
        <property name="firstName" value="Paulo" />
        <property name="lastName" value="Coelho" />
        <property name="dateOfBirth" value="24 August 1947" />
        <property name="country" value="India" />
    </bean>
    

    如果您像下面这样定义验证器 bean,Spring 会在部署时验证 ID 为 osho 和 Paulo 的 bean。如果在配置文件中没有找到任何 bean,那么 spring 会抛出 BeanDefinitionStoreException。

    <bean id="validatorBean" class="com.sample.test.BeansValidator">
        <property name="author1">
            <idref bean="osho" />
        </property>
    
        <property name="author2">
            <idref bean="paulo" />
        </property>
    </bean>
    

    以下是完整的工作应用程序。

    package com.sample.pojo;
    
    public class Author {
        private String firstName;
        private String lastName;
        private String dateOfBirth;
        private String country;
    
        public String getFirstName() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getDateOfBirth() {
            return dateOfBirth;
        }
    
        public void setDateOfBirth(String dateOfBirth) {
            this.dateOfBirth = dateOfBirth;
        }
    
        public String getCountry() {
            return country;
        }
    
        public void setCountry(String country) {
            this.country = country;
        }
    
        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("Author [firstName=").append(firstName).append(", lastName=").append(lastName)
                    .append(", dateOfBirth=").append(dateOfBirth).append(", country=").append(country).append("]");
            return builder.toString();
        }
    
    }
    

    BeansValidator.java

    package com.sample.test;
    
        public class BeansValidator {
            private String author1;
            private String author2;
    
            public String getAuthor1() {
                return author1;
            }
    
            public void setAuthor1(String author1) {
                this.author1 = author1;
            }
    
            public String getAuthor2() {
                return author2;
            }
    
            public void setAuthor2(String author2) {
                this.author2 = author2;
            }
    
        }
    

    myConfiguration.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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <bean id="osho" class="com.sample.pojo.Author">
            <property name="firstName" value="Osho" />
            <property name="lastName" value="Jain" />
            <property name="dateOfBirth" value="11 December 1931" />
            <property name="country" value="India" />
        </bean>
    
        <bean id="paulo" class="com.sample.pojo.Author">
            <property name="firstName" value="Paulo" />
            <property name="lastName" value="Coelho" />
            <property name="dateOfBirth" value="24 August 1947" />
            <property name="country" value="India" />
        </bean>
    
        <bean id="validatorBean" class="com.sample.test.BeansValidator">
            <property name="author1">
                <idref bean="osho" />
            </property>
    
            <property name="author2">
                <idref bean="paulo" />
            </property>
        </bean>
    
    </beans>
    

    运行 HelloWorld.java,不会出现任何异常。

    package com.sample.test;
    
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
    
        public class HelloWorld {
            public static void main(String args[]) {
                ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { "myConfiguration.xml" });
    
                ((ClassPathXmlApplicationContext) context).close();
            }
        }
    

    现在更新 myConfiguration.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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    
        <bean id="osho" class="com.sample.pojo.Author">
            <property name="firstName" value="Osho" />
            <property name="lastName" value="Jain" />
            <property name="dateOfBirth" value="11 December 1931" />
            <property name="country" value="India" />
        </bean>
    
        <bean id="paulo" class="com.sample.pojo.Author">
            <property name="firstName" value="Paulo" />
            <property name="lastName" value="Coelho" />
            <property name="dateOfBirth" value="24 August 1947" />
            <property name="country" value="India" />
        </bean>
    
        <bean id="validatorBean" class="com.sample.test.BeansValidator">
            <property name="author1">
                <idref bean="Krishna" />
            </property>
    
            <property name="author2">
                <idref bean="paulo" />
            </property>
        </bean>
    
    </beans>
    

    当您看到配置文件时,validatorBean 检查 id 为“Krishna”的 bean。

    <bean id="validatorBean" class="com.sample.test.BeansValidator">
            <property name="author1">
                <idref bean="Krishna" />
            </property>
    
            <property name="author2">
                <idref bean="paulo" />
            </property>
        </bean>
    

    由于 id 为“Krishna”的 bean 不存在,您最终会出现以下错误。

    Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'validatorBean' defined in class path resource [myConfiguration.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean name 'Krishna' in bean reference for bean property 'author1'
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:751)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
        at com.sample.test.HelloWorld.main(HelloWorld.java:8)
    

    【讨论】:

      【解决方案4】:

      我必须说我有点困惑。在您提供 praveen 的示例中,它将起作用,因为您的类中的属性是 String 类型,但在 yapkm01 的示例中,属性是 Point 类型,您将得到提到的异常。为了能够使用 idref,他似乎必须引入另一个 String 类型的属性,这里是“消息”,然后代码看起来像这样:

      <property name="message">
          <idref bean="zeroPoint" />
      </property>
      
      <property name="pointA" ref="zeroPoint"/>
      

      【讨论】:

        【解决方案5】:

        你没有做错任何事。您应该在代码中使用&lt;ref&gt; 而不是&lt;idref&gt;&lt;idref&gt; 标记用于创建一个字符串类型的值,该值等于被引用 bean 的 ID,用于验证目的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-06-29
          • 1970-01-01
          • 1970-01-01
          • 2013-08-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多