让我们举个例子说明:
拥有这个bean:
public class Foo {
private String name;
Foo(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
这项服务:
public class FooService {
private Foo foo;
FooService(Foo foo) {
this.foo = foo;
}
Foo getFoo() {
return this.foo;
}
}
给出以下Spring配置:
@Configuration
public class SpringContext {
// @Bean
// Foo foo() {
// return new Foo("foo");
// }
@Bean
@Autowired(required = false)
FooService fooService(Foo foo) {
if (foo == null) {
return new FooService(new Foo("foo"));
}
return new FooService(foo);
}
}
为了完整起见,这是一个简单的单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringContext.class})
public class SpringAppTests {
@Autowired
private FooService fooService;
@Test
public void testGetName() {
Assert.assertEquals("foo", fooService.getFoo().getName());
}
}
然后加载上下文将抛出NoSuchBeanDefinitionException(Foo)。
在这个例子中,任何人都可以看到任何错误/缺失,或者为我提供理由吗?
谢谢!基督教
答案 0 :(得分:6)
除了其他答案:
问题是spring在注入参数时不会考虑required=false
。见ConstructorResolver
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
第二个参数总是true
:
public DependencyDescriptor(MethodParameter methodParameter, boolean required)
编辑: Spring使用ConstructorResolver
“真正的”构造注入
@Autowired(required=false) // required=false WILL NOT WORK
public FooService(Foo foo){
...
}
工厂方法
@Bean
@Autowired(required=false) // required=false WILL NOT WORK
FooService fooService(Foo foo) {
if (foo == null) {
return new FooService(new Foo("foo"));
}
return new FooService(foo);
}
因此,在这两种情况下都会忽略required
属性。
答案 1 :(得分:3)
您的语法错误。 @Autowired(required = false)
需要与Foo
相关联。
例如:
@Configuration
public class SpringContext {
@Autowired(required = false)
private Foo foo;
@Bean
FooService fooService() {
if (foo == null) {
return new FooService(new Foo("foo"));
}
return new FooService(foo);
}
}
答案 2 :(得分:2)
尝试
@Configuration
public class SpringContext {
// @Bean
// Foo foo() {
// return new Foo("foo");
// }
@Autowired(required = false)
Foo foo;
@Bean
FooService fooService() {
if (this.foo == null) {
return new FooService(new Foo("foo"));
}
return new FooService(this.foo);
}
}