简体   繁体   English

Spring依赖注入问题

[英]Spring dependency injection issue

I have a bean I am trying to configure in Spring context using Constructor injection.我有一个 bean,我试图使用构造函数注入在 Spring 上下文中进行配置。 When I pass subclass for one of the constructor arguments, the bean is instantiated by Spring container only if I do not specify the "type" attribute.当我为构造函数参数之一传递子类时,仅当我不指定“type”属性时,Spring 容器才会实例化 bean。 Would anybody have any idea what's wrong?有人会知道出了什么问题吗? Below are more specifics.下面是更具体的内容。

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

class ConcreteClass extends SomeAbstractBase{
   //
} 

Spring configs (First and second do not work but the third one using type attribute works)- Config I- Spring 配置(第一个和第二个不起作用,但第三个使用 type 属性有效)- 配置 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-配置 III-

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

I get the following exception at initialization-我在初始化时收到以下异常-

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jedispool' defined in class path resource [cache-spring-config.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)线程“main”中的异常 org.springframework.beans.factory.BeanCreationException:创建名为“jedispool”的 bean 在类路径资源 [cache-spring-config.xml] 中定义时出错:无法解析匹配的构造函数(提示:指定索引/简单参数的类型/名称参数以避免类型歧义)

Why would neither of the first or second config work?为什么第一个或第二个配置都不起作用?

Thank you谢谢

Type argument accept only the full qualified type (because if not spring cannot determine exactly the package and the type will not match your class):类型参数只接受完全限定的类型(因为如果不是,spring 无法准确确定包,并且类型将与您的类不匹配):

So you need to use the canonical name of your class to be a type所以你需要使用你的类的规范名称作为一个类型

ConcreteClass => com.your.app.ConcreteClass

A class is not just a name, is a package + name (too be short)一个类不仅仅是一个名字,是一个包+名字(太短了)

I believe the error you had appeared because you had static nested classes.我相信你出现的错误是因为你有static嵌套类。 Here's an SSCCE这是一个 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 {
    }
}

With spring.xml containingspring.xml包含

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

The above fails with a UnsatisfiedDependencyException .以上失败并出现UnsatisfiedDependencyException In this specific example, the class attribute isn't used correctly.在此特定示例中,未正确使用class属性。 The fully qualified class name for ConcreteClass is test.Test$ConcreteClass , not test.Test.ConcreteClass as I've specified. ConcreteClass的完全限定类名称是test.Test$ConcreteClass ,而不是我指定的test.Test.ConcreteClass The same applies to MyClass and SomeAbstractBase .这同样适用于MyClassSomeAbstractBase

However, specifying test.Test.ConcreteClass in the class attribute for the concreteclass bean doesn't fail because at some point during processing of bean declarations, Spring tries to resolve the class String into a Class object using Class.forName(String) .但是,指定test.Test.ConcreteClassclass的属性concreteclass ,因为在bean声明的处理期间的某一时刻豆不会失败,春尝试解析class String转换为Class使用对象Class.forName(String) It will call ClassUtils.forName(String, ClassLoader) to do this.它将调用ClassUtils.forName(String, ClassLoader)来执行此操作。 Initially it will fail because there is no such class test.Test.ConcreteClass .最初它会失败,因为没有这样的类test.Test.ConcreteClass However, this is done in a try-catch which on ClassNotFoundException will transform the String class name from test.Test.ConcreteClass to test.Test$ConcreteClass and try again.但是,这是在try-catch中完成的, ClassNotFoundException会将String类名从test.Test.ConcreteClasstest.Test$ConcreteClass试。 It will work and correctly create a bean of type test.Test$ConcreteClass for your concreteclass bean.它将工作并为您的concreteclass bean 正确创建类型为test.Test$ConcreteClass的 bean。

When it tries to create your myclass bean, however, it does not apply such logic for resolving which constructor to use and therefore cannot understand that with the type attribute value of test.Test.SomeAbstractBase , you actually meant test.Test$SomeAbstractBase , so it fails saying the type is ambiguous.当它试图创建myclass绿豆,但是,它并没有解决其构造函数中使用应用这样的逻辑,因此不能明白与type的属性值test.Test.SomeAbstractBase ,你实际上意味着test.Test$SomeAbstractBase ,所以它没有说类型不明确。

Change your bean declarations to correct types将 bean 声明更改为正确的类型

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

and it will work.它会起作用。

Take a look at kakawait's answer , you need to specify the fully qualified class name for the bean you are trying to instantiate.看看kakawait 的回答,您需要为您尝试实例化的 bean 指定完全限定的类名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM