Spring 将列表自动装配到 bean 中导致 NoSuchBeanDefinitionException
Spring Autowiring a list into a bean results in a NoSuchBeanDefinitionException
在 Spring 3.1.3.RELEASE 项目中,我想创建并自动装配一个包含某些服务枚举的列表。
不幸的是,自动装配失败(NoSuchBeanDefinitionException),而我可以在上下文中检索 bean 并手动装配依赖项。
这是一个展示问题的小测试用例(使用 Spring 3.1.3 和 JUnit):
XML上下文(int包/垃圾):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="junk"/>
<util:list id="myList" value-type="junk.GreatThings">
<value>SUPER</value>
<value>COOL</value>
</util:list>
</beans>
枚举:
package junk;
public enum GreatThings {AMAZING, GREAT, SUPER, COOL}
测试class(在垃圾包中——为清楚起见,我删除了导入):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport {
@Autowired @Qualifier("myList") List<GreatThings> greatThings;
@Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
这会导致 NoSuchBeanDefinitionException。
我尝试将 @Qualifier 与我的 bean id 放在一起,以帮助 Spring 执行连接但没有成功。
但是我的 IDE 能够自行检测接线:
如果我使用 Spring 生命周期回调取回 bean 并手动连接它,就没问题了。
编译运行良好的版本:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport implements ApplicationContextAware
{
ApplicationContext ctx;
List<GreatThings> greatThings;
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {this.ctx = ctx;}
@PostConstruct
public void manualWiring() {greatThings = (List<GreatThings>) ctx.getBean("myList");}
@Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
这种情况下的自动装配有什么问题?
如 reference documentation 中所述,将 @Autowired
注释放在类型化集合上意味着 "find all beans of the given type (GreatThings
in your case), put them in a collection and inject that collection"。您收到异常是因为没有声明 GreatThings
类型的 bean。
问题是没有简单的方法可以将枚举值声明为 bean。老实说,我又没有看到用例。
泛型似乎有问题。
使用 Spring 4.1 我能够执行此代码:其中 greatThings
的类型为 List<Object>
@Qualifier("myList")
@Autowired List<Object> greatThings;
@Test
public void testSuperCool() {
Assert.assertThat(greatThings, Matchers.hasSize(2));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.SUPER));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.COOL));
}
在 Spring 3.1.3.RELEASE 项目中,我想创建并自动装配一个包含某些服务枚举的列表。
不幸的是,自动装配失败(NoSuchBeanDefinitionException),而我可以在上下文中检索 bean 并手动装配依赖项。
这是一个展示问题的小测试用例(使用 Spring 3.1.3 和 JUnit):
XML上下文(int包/垃圾):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="junk"/>
<util:list id="myList" value-type="junk.GreatThings">
<value>SUPER</value>
<value>COOL</value>
</util:list>
</beans>
枚举:
package junk;
public enum GreatThings {AMAZING, GREAT, SUPER, COOL}
测试class(在垃圾包中——为清楚起见,我删除了导入):
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport {
@Autowired @Qualifier("myList") List<GreatThings> greatThings;
@Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
这会导致 NoSuchBeanDefinitionException。 我尝试将 @Qualifier 与我的 bean id 放在一起,以帮助 Spring 执行连接但没有成功。
但是我的 IDE 能够自行检测接线:
如果我使用 Spring 生命周期回调取回 bean 并手动连接它,就没问题了。
编译运行良好的版本:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport implements ApplicationContextAware
{
ApplicationContext ctx;
List<GreatThings> greatThings;
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {this.ctx = ctx;}
@PostConstruct
public void manualWiring() {greatThings = (List<GreatThings>) ctx.getBean("myList");}
@Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
这种情况下的自动装配有什么问题?
如 reference documentation 中所述,将 @Autowired
注释放在类型化集合上意味着 "find all beans of the given type (GreatThings
in your case), put them in a collection and inject that collection"。您收到异常是因为没有声明 GreatThings
类型的 bean。
问题是没有简单的方法可以将枚举值声明为 bean。老实说,我又没有看到用例。
泛型似乎有问题。
使用 Spring 4.1 我能够执行此代码:其中 greatThings
的类型为 List<Object>
@Qualifier("myList")
@Autowired List<Object> greatThings;
@Test
public void testSuperCool() {
Assert.assertThat(greatThings, Matchers.hasSize(2));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.SUPER));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.COOL));
}