web-dev-qa-db-ja.com

NoSuchBeanDefinitionExceptionを与えるコンストラクターの@Autowired(required = false)

Springアプリケーションでは、コンストラクターで@Autowired(required=false)を使用しました。これは、自動配線されるBeanがxmlファイルで使用できない場合、(_required=false_)が記述されているため、NoSuchBeanDefinitionExceptionをスローしないことを意味します。しかし、UnsatisfiedDependencyExceptionNoSuchBeanDefinitionExceptionの例外が発生しています。

- - テキストエディタ

_public class TextEditor {

    private SpellChecker x;
    private String name;    

    @Autowired(required=false)
    public TextEditor(SpellChecker x) {
        System.out.println("Inside TextEditor constructor." );
        this.x = x;
    }


    public SpellChecker getY() {
        return x;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void spellCheck() {
        x.checkSpelling();
    }
}
_

---- SpellChecker

_public class SpellChecker {
    public SpellChecker() {
        System.out.println("Inside SpellChecker constructor.");
    }

    public void checkSpelling() {
        System.out.println("Inside checkSpelling.");
    }
}
_

---- Beans.xml

_<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aks="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    aks:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <context:annotation-config />

    <bean id="textEditor" class="com.tutorialspoint.TextEditor">
        <!-- <property name="x" ref="a" /> -->
        <property name="name" value="Generic Text Editor" />
    </bean>

    <!-- <bean id="a" class="com.tutorialspoint.SpellChecker" /> -->

</beans>

---- MainApp
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "Beans.xml");//Beans.xml, Beans1.xml
        TextEditor te = (TextEditor) context.getBean("textEditor");
        //te.spellCheck();
        System.out.println(te.getY());
    }
}
_

---コンソール(実際の結果)

_Apr 24, 2014 4:30:00 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@15eb0a9: startup date [Thu Apr 24 16:30:00 IST 2014]; root of context hierarchy
Apr 24, 2014 4:30:00 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [Beans.xml]
Apr 24, 2014 4:30:00 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d9c06: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,textEditor]; root of factory hierarchy
Apr 24, 2014 4:30:00 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@2d9c06: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,textEditor]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'textEditor' defined in class path resource [Beans.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.tutorialspoint.SpellChecker]: : No matching bean of type [com.tutorialspoint.SpellChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.tutorialspoint.SpellChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.Java:730)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.Java:196)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.Java:1002)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.Java:906)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.Java:484)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.Java:455)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.Java:293)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.Java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.Java:290)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.Java:192)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.Java:585)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.Java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:425)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.Java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.Java:83)
    at com.tutorialspoint.MainApp.main(MainApp.Java:8)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.tutorialspoint.SpellChecker] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.Java:924)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.Java:793)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.Java:707)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.Java:795)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.Java:723)
    ... 15 more
_

---コンストラクターに@Autowire(required=false)が記載されているため、期待される結果プログラムはExceptionなしで実行する必要があります。 Beanが見つからなくても、(_required=false_)が記述されているため、例外は発生しません。

13
user1501192

この例外は、required = falseがnullを挿入することを意味しないために発生します。 Springをコンストラクターに適用すると、インスタンスの作成に最適なコンストラクターを決定しようとします。この場合、SpellCheckerを必要とするコンストラクターは1つだけですが、そのタイプのオブジェクトはありません。

Springドキュメントで参照されているように( http://docs.spring.io/spring/docs/4.0.x/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html ) :

特定のBeanクラスの1つのコンストラクター(最大)のみがこのアノテーションを保持でき、SpringBeanとして使用されるときにコンストラクターが自動配線されることを示します。このようなコンストラクターはパブリックである必要はありません。

とにかく、デフォルトのコンストラクター(プライベートにすることもできます)を追加して、Springが@Autowiredマジックを実行できない場合に、そのコンストラクターを使用するようにすることができます。 TextEditorクラスに、次のものを追加できます。

@Deprecated
private TextEditor() {
    // You could leave x = null or create a default value for that field 
    // if you have one (eg. x = new DefaultSpellChecker();)
}

@Deprecatedは、誰も使用しないプライベートコンストラクターがあることをコンパイラーが警告するのを避けるために使用されることに注意してください。

14
Nicola

私も同様の問題を抱えていました。実際には、いくつかのコンストラクターを持つことができます

@Autowired(required = false)

ただし、@ Autowiredアノテーションには少なくとも1つの引数が必要なため、デフォルト(引数なし)のコンストラクターにこのアノテーションを追加できないことに注意してください。

3
Geniy