Spring依赖注入问题

时间:2013-10-11 14:20:38

标签: spring

我正在尝试使用Constructor注入在Spring上下文中配置一个bean。当我为其中一个构造函数参数传递子类时,只有在我没有指定“type”属性时,bean才会被Spring容器实例化。有人会知道什么是错的吗?以下是更具体的内容。

class MyClass{
   public MyClass(SomeAbstractBase absObject){
      //do stuff
   }
}

class ConcreteClass extends SomeAbstractBase{
   //
} 

Spring配置(第一个和第二个不起作用,但第三个使用类型属性工作) - 配置I -

<bean id="concreteclass" 
         class="ConcreteClass"/>
<bean id="myclass" 
        class="MyClass">
        <constructor-arg type="ConcreteClass" ref="concreteclass"/>
</bean>

Config II -

<bean id="concreteclass" 
         class="ConcreteClass"/>
<bean id="myclass" 
        class="MyClass">
        <constructor-arg type="SomeAbstractBase" ref="concreteclass"/>
</bean>

Config III -

 <bean id="concreteclass" 
             class="ConcreteClass"/>
    <bean id="myclass" 
            class="MyClass">
            <constructor-arg ref="concreteclass"/>
    </bean>

我在初始化时遇到以下异常 -

  

线程“main”中的异常   org.springframework.beans.factory.BeanCreationException:错误   在类路径资源中定义名为'jedispool'的bean   [cache-spring-config.xml]:无法解析匹配的构造函数   (提示:为简单参数指定索引/类型/名称参数   避免类型歧义)

为什么第一个或第二个配置都不起作用?

谢谢

2 个答案:

答案 0 :(得分:0)

类型参数只接受完全限定类型(因为如果不是spring,则无法准确确定包,并且类型与您的类不匹配):

因此,您需要使用类的规范名称作为类型

ConcreteClass => com.your.app.ConcreteClass

一个类不仅仅是一个名称,是一个包+名称(也是简短的)

答案 1 :(得分:0)

我相信您出现的错误是因为您有static嵌套类。这是一个SSCCE

package test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
    public static void main(String[] args) throws Exception {
        System.out.println(MyClass.class.getName());
        System.out.println(ConcreteClass.class.getName());
        System.out.println(SomeAbstractBase.class.getName());
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");  
    }
    static class MyClass {
        public MyClass(SomeAbstractBase absObject) {
        }
    }
    static class ConcreteClass extends SomeAbstractBase {
        //
    }
    static abstract class SomeAbstractBase {
    }
}

spring.xml包含

<bean id="concreteclass" class="test.Test.ConcreteClass" />
<bean id="myclass" class="test.Test.MyClass">
    <constructor-arg  type="test.Test.SomeAbstractBase" ref="concreteclass" />
</bean>

上述内容因UnsatisfiedDependencyException而失败。在此特定示例中,未正确使用class属性。 ConcreteClass的完全限定类名是test.Test$ConcreteClass,而不是我指定的test.Test.ConcreteClass。这同样适用于MyClassSomeAbstractBase

但是,在test.Test.ConcreteClass bean的class属性中指定concreteclass并不会失败,因为在处理bean声明期间的某个时刻,Spring会尝试解析class使用Class将字符串转换为Class.forName(String)对象。它会调用ClassUtils.forName(String, ClassLoader)来执行此操作。最初它会失败,因为没有这样的类test.Test.ConcreteClass。但是,这是在try-catch ClassNotFoundException中完成的,String会将test.Test.ConcreteClass班级名称从test.Test$ConcreteClass转换为test.Test$ConcreteClass,然后重试。它将为您的concreteclass bean正常创建一个myclass类型的bean。

但是,当它尝试创建您的type bean时,它不会应用这样的逻辑来解析要使用的构造函数,因此无法理解test.Test.SomeAbstractBase属性值test.Test$SomeAbstractBase ,你实际上是指<bean id="concreteclass" class="test.Test$ConcreteClass" /> <bean id="myclass" class="test.Test$MyClass"> <constructor-arg type="test.Test$SomeAbstractBase" ref="concreteclass" /> </bean> ,所以它不能说类型不明确。

将bean声明更改为正确的类型

{{1}}

它会起作用。

看一下kakawait's answer,你需要为你想要实例化的bean指定完全限定的类名。