Автоматическое подключение списка с помощью схемы util дает NoSuchBeanDefinitionException


у меня есть боб, который я хочу ввести с именованным списком, используя пространство имен Spring util <util:list id="myList"> но весна ищет коллекцию бобов типа String вместо этого. Мой сломанный тест:

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

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

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

мой контекст:

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

но я

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)

что меня скорее озадачивает, поскольку я полагал, что это будет так, как ожидалось.

3 87

3 ответа:

это связано с довольно неясной частью поведения @Autowired, указанной в 3.11.2. @Autowired:

также возможно обеспечить все фасоль определенного типа из ApplicationContext путем добавления аннотация к полю или методу, который ожидает массив такого типа...

то же самое относится и к типизированным коллекциям...

другими словами, говоря @Autowired @Qualifier("myList") List<String>, вы на самом деле просите "дайте мне список всех бобов типа java.lang.String которые имеют квалификатор "myList".

решение упомянуто в 3.11.3. Точная настройка аннотации на основе автопроводки с квалификаторами:

если вы намерены выразить аннотация-управляемая впрыска по имени, не используйте в первую очередь @Autowired - даже если технически способен ссылаться к имени Боба через @Qualifier ценности. Вместо этого предпочтите JSR-250 @Resource аннотированию семантически определенными для идентификации специфический целевой компонент своим уникальное имя, с объявленным типом не имеет значения для сопоставления процесс.

как конкретное следствие этого семантическое различие, бобы, которые являются сами определяются как коллекция или тип карты не может быть введен через @Autowired так как тип соответствия не является правильно применимо к ним. использовать @Resource для таких бобов, ссылаясь на конкретная коллекция / карта bean by уникальный имя.

так что используйте это в своем тесте, и он отлично работает:

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

еще одна вещь, которая может произойти, заключается в том, что вы автоматически подключаете свойство Боба. В таком случае вам не нужно автоматически подключать его, а просто создать метод setter и использовать тег свойства в определении bean (при использовании 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>

и класс:

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

посмотреть, нет @Autowired аннотаций в классе.

при использовании JBoss 6.1 я обнаружил, что аннотация @Resource вызвала сбой моего развертывания (деталь опущена как не относящаяся к вопросу).

общий для всех серверов приложений является использование аннотации @Inject (JSR-330).