0

我有一个 bean,我正在尝试使用构造函数注入在 Spring 上下文中进行配置。当我为构造函数参数之一传递子类时,只有当我没有指定“类型”属性时,才会由 Spring 容器实例化 bean。有人知道出了什么问题吗?以下是更多细节。

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

class ConcreteClass extends SomeAbstractBase{
   //
} 

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

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

配置二-

<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>

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

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

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

谢谢

4

2 回答 2

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属性未正确使用。的完全限定类名ConcreteClassis test.Test$ConcreteClass,而不是test.Test.ConcreteClass我指定的。这同样适用于MyClassSomeAbstractBase

但是,在 bean 的属性中指定不会test.Test.ConcreteClass失败classconcreteclass因为在处理 bean 声明期间的某个时刻,Spring 尝试使用. 它会要求这样做。最初它会失败,因为没有这样的类。但是,这是在which on将类名从to转换并重试的情况下完成的。它将工作并为您的 bean 正确创建一个类型的bean。classClassClass.forName(String)ClassUtils.forName(String, ClassLoader)test.Test.ConcreteClasstry-catchClassNotFoundExceptionStringtest.Test.ConcreteClasstest.Test$ConcreteClasstest.Test$ConcreteClassconcreteclass

但是,当它尝试创建您的myclassbean 时,它不会应用这种逻辑来解析要使用的构造函数,因此无法理解使用 的type属性值test.Test.SomeAbstractBase,您实际上是指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 的回答,您需要为您尝试实例化的 bean 指定完全限定的类名。

于 2013-10-11T16:20:01.203 回答
0

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

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

ConcreteClass => com.your.app.ConcreteClass

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

于 2013-10-11T14:29:57.803 回答