2013-10-11 160 views
0

我有一个bean我想在使用构造函数注入的Spring上下文中配置。当我传递一个构造函数参数的子类时,只有当我没有指定“type”属性时,bean才由Spring容器实例化。有人知道有什么问题吗?以下是更具体的。春天依赖注入问题

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

class ConcreteClass extends SomeAbstractBase{ 
    // 
} 

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

配置II-

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

配置III-

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

我得到initialization-

异常以下异常线程“main” org.springframework.beans.factory.BeanCreationException:错误 创建名为“jedispool”豆中的类路径资源定义 [的cache春天-config.xml中]:无法解析匹配构造 (提示:对于简单的参数指定索引/型号/名称参数 避免歧义型)

第一或第二配置工作,为什么会没有?

谢谢

+0

对于上面的例子,你使用静态嵌套类吗? –

回答

0

类型参数只接受完整合格的类型(因为如果不是弹簧不能准确确定包和类型将不匹配您的类):

所以你需要使用规范名称你的类是一种类型的

ConcreteClass => com.your.app.ConcreteClass 

类是不只是一个名字,是一个包+域名(太短)

+0

这对第三个配置也会失败。 –

+0

嗡嗡声我尝试了我的webapp,在类型参数工作中使用规范类名。但是在使用ref时没有理由指定类型,spring会自行解析。 – Kakawait

+0

我的意思是它会在'concrete class'的bean声明中失败,其中OP也指定了一个类名。 –

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

然而,在class属性为concreteclass豆并不在bean声明的加工过程中的一些点,因为无法确定test.Test.ConcreteClass,春尝试解析class字符串到使用Class.forName(String)一个Class对象。它会呼叫ClassUtils.forName(String, ClassLoader)来做到这一点。最初它会失败,因为没有这样的类test.Test.ConcreteClass。然而,这是在try-catch中完成的,其在ClassNotFoundExceptionString类别名称从test.Test.ConcreteClass变换为test.Test$ConcreteClass并且再试一次。它将正常工作并为您的concreteclass bean正确创建一个类型为test.Test$ConcreteClass的bean。

当它试图创建myclass豆,但是,它并没有解决它的构造函数使用应用这样的逻辑,因此无法理解,随着test.Test.SomeAbstractBasetype属性值,你实际上意味着test.Test$SomeAbstractBase,所以它不能说的类型不明确。

改变你的bean声明纠正各类

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

,它会工作。

看看kakawait's answer,您需要为您尝试实例化的bean指定完全限定的类名称。