我正在尝试使用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]:无法解析匹配的构造函数 (提示:为简单参数指定索引/类型/名称参数 避免类型歧义)
为什么第一个或第二个配置都不起作用?
谢谢
答案 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
。这同样适用于MyClass
和SomeAbstractBase
。
但是,在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指定完全限定的类名。