91 Stimmen

Die automatische Verdrahtung einer Liste mit util-Schema führt zu NoSuchBeanDefinitionException

Ich habe eine Bohne, die ich mit einer benannten Liste mit Spring util Namespace injizieren möchte <util:list id="myList"> aber Spring sucht stattdessen nach einer Sammlung von Beans vom Typ String. Mein fehlerhafter Test ist:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class ListInjectionTest {

    @Autowired @Qualifier("myList") private List<String> stringList;

    @Test public void testNotNull() {
        TestCase.assertNotNull("stringList not null", stringList);
    }
}

Mein Kontext ist:

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:util="http://www.springframework.org/schema/util"
   xmlns="http://www.springframework.org/schema/beans"
   xmlns:context="http://www.springframework.org/schema/context"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">

   <util:list id="myList">
       <value>foo</value>
       <value>bar</value>
   </util:list>

</beans>

Aber ich bekomme

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [java.lang.String] found for dependency [collection of java.lang.String]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=myList)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:726)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:571)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:412)

Das verwundert mich etwas, da ich dachte, dass es so funktionieren würde.

177voto

skaffman Punkte 389758

Dies ist auf einen eher obskuren Teil des Verhaltens von @Autowired zurückzuführen, der in 3.11.2. @Autowired :

Es ist auch möglich, alle Bohnen eines bestimmten Typs aus der ApplicationContext durch Hinzufügen der Anmerkung zu einem Feld oder einer Methode, die ein Array dieses Typs erwartet...

Das Gleiche gilt für typisierte Sammlungen...

Mit anderen Worten, durch die Aussage @Autowired @Qualifier("myList") List<String> fragen Sie eigentlich nach "Gib mir die Liste aller Bohnen des Typs java.lang.String die den Bezeichner "myList" haben.

Die Lösung wird erwähnt in 3.11.3. Feinabstimmung der annotationsbasierten automatischen Verdrahtung mit Qualifikatoren :

Wenn Sie Folgendes zum Ausdruck bringen wollen annotationsgesteuerte Injektion durch Namen auszudrücken, verwenden Sie nicht primär @Autowired - selbst technisch in der Lage ist, sich auf einen auf einen Bean-Namen durch @Qualifier Werte. Bevorzugen Sie stattdessen die JSR-250 @Resource Bemerkung, die lautet semantisch definiert ist, um eine bestimmte spezifische Zielkomponente durch ihren eindeutigen Namen zu identifizieren, wobei der deklarierte Typ für den Abgleich irrelevant ist Prozess irrelevant ist.

Eine besondere Folge davon ist, dass semantischen Unterschieds sind Bohnen, die selbst als Collection oder Map definiert sind Map-Typ definiert sind, können nicht über @Autowired da der Typabgleich nicht nicht richtig auf sie anwendbar ist. Verwenden Sie @Resource für solche Bohnen und verweist auf die spezifische Sammlung/Map-Bean durch eindeutigen Namen.

Verwenden Sie dies also in Ihrem Test, und es funktioniert gut:

@Resource(name="myList") private List<String> stringList;

0voto

juliangonzalez Punkte 3973

Eine andere Sache, die passieren könnte, ist, dass Sie eine Eigenschaft einer Bean autowiring sind. In einem solchen Fall brauchen Sie die Eigenschaft nicht automatisch zuzuweisen, sondern erstellen nur die Setter-Methode und verwenden das Property-Tag in der Bean-Definition (bei Verwendung von xml):

<bean id="cleaningUpOldFilesTasklet" class="com.example.mypackage.batch.tasklets.CleanUpOldFilesTasklet">
    <property name="directoriesToClean">
        <list>
            <value>asfs</value>
            <value>fvdvd</value>
            <value>sdfsfcc</value>
            <value>eeerer</value>
            <value>rerrer</value>
        </list>
    </property>
</bean>

Und die Klasse:

public class CleanUpOldFilesTasklet extends TransferingFilesTasklet implements Tasklet{

private long pastMillisForExpiration;
private final String dateFormat = "MM.dd";
Date currentDate = null;

List<String> directoriesToClean;

public void setDirectoriesToClean(List<String> directories){
    List<String> dirs = new ArrayList<>();
    for(String directory : directories){
        dirs.add(getSanitizedDir(directory));
    }
    this.directoriesToClean = dirs;
}

Siehe, nein @Autowired Bemerkung in der Klasse.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X