使用util模式自动连接List会导致NoSuchBeanDefinitionExceptionexception

我有一个bean,我想使用Spring util命名空间<util:list id="myList">注入一个命名列表,但是Spring正在寻找types为String的bean的集合。 我的破碎testing是:

 @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.11.2中指定的@ Autowired行为的一个相当模糊的部分。 @Autowired :

通过将注解添加到需要该types的数组的字段或方法,可以从ApplicationContext提供特定types的所有Bean …

同样适用于键入的集合…

换句话说,通过说@Autowired @Qualifier("myList") List<String> ,实际上是要求“给我所有具有限定符”myList“的java.lang.Stringtypes的bean的列表。

解决方法在3.11.3中提到。 使用限定符微调基于注释的自动assembly :

如果您打算按名称表示注解驱动注入,则不要主要使用@Autowired – 即使技术上能够通过@Qualifier值引用bean名称。 相反,更喜欢JSR-250 @Resource注释,它的语义定义是通过其唯一的名称来标识一个特定的目标组件,声明的types与匹配过程无关。

作为这种语义差异的一个特定结果,自身被定义为集合或映射types的bean不能通过@Autowired注入,因为types匹配不适用于它们。 对这样的bean使用@Resource ,通过唯一的名称引用特定的集合/映射bean。

所以在你的testing中使用这个,它工作正常:

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

如果使用JBoss 6.1,我发现@Resource注解导致我的部署失败(细节被忽略,与问题无关)。

所有应用程序服务器的一般select是使用@Inject注释( JSR-330 )。

另一件可能发生的事情是,你正在自动assembly一个bean的属性。 在这种情况下,你不需要autowire它,但只需创buildsetter方法并在bean定义(使用xml)时使用property标签:

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

和class级:

 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注释。