【发布时间】:2014-02-13 07:42:26
【问题描述】:
我的 Spring 上下文中有一个 Provider<Foo> 类型的 bean。我想@Autowire 那个 bean 进入另一个类。
@Autowired
private Provider<Foo> fooProvider;
但是,Spring 看到了这一点,并决定我必须在我的上下文中定义了一个 Foo 类型的 bean,并且我希望将它包装在 Provider 中,以便 Spring 可以管理它的范围。
这不是我想要的;我没有Foo,我有Provider<Foo>。春天抱怨:
org.springframework.beans.factory.NoSuchBeanDefinitionException: 没有为依赖项找到类型为 [my.package.Foo] 的匹配 bean:预计至少有 1 个 bean 有资格作为此依赖项的自动装配候选者。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
如何让 Spring 不那么聪明,只自动装配我想要的类型?
更新
感谢您的提问。我创建了一个测试用例来说明我的问题:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:foo-context.xml")
@TestExecutionListeners({
DependencyInjectionTestExecutionListener.class
})
public class FooProviderTest {
@Autowired
private javax.inject.Provider<Foo> fooProvider;
@Test
public void verifyFooProviderAutowired() {
assertEquals("foo", fooProvider.get().getFooName());
}
}
class Foo {
public String getFooName() {
return "foo";
}
}
class SimpleFooProvider implements javax.inject.Provider<Foo> {
@Override
public Foo get() {
return new Foo();
}
}
foo-context.xml文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi: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="fooProvider" class="example.SimpleFooProvider"/>
</beans>
测试的输出:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [example.Foo] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:947)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:816)
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyObjectFactory.getObject(DefaultListableBeanFactory.java:1035)
at org.springframework.beans.factory.support.DefaultListableBeanFactory$DependencyProvider.get(DefaultListableBeanFactory.java:1051)
at example.FooProviderTest.verifyFooProviderAutowired(FooProviderTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
请注意,测试不会在断言上失败;它无法初始化应用程序上下文。
奇怪的是,将测试字段的声明类型从 Provider<Foo> 显式更改为 SimpleFooProvider 会导致测试通过而没有任何抱怨。也就是说,
@Autowired
private SimpleFooProvider fooProvider;
【问题讨论】:
-
您的 Provider 是从
Map类型还是List类型扩展而来的,如果是这样,这可能是 Spring 触发此行为的原因。 -
@BijuKunjummen 我相信是
javax.inject.Provider。 -
您能在上下文中向我们展示您对
Providerbean 的声明吗?我还想查看更多异常堆栈跟踪?您是在初始化时还是在尝试使用fooProvider时得到它? -
是的,你是对的@SotiriosDelimanolis。非常整洁。
-
感谢大家的提问。我已更新我的问题以澄清问题。