Let explain with an example:
Having this bean:
public class Foo {
private String name;
Foo(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
And this service:
public class FooService {
private Foo foo;
FooService(Foo foo) {
this.foo = foo;
}
Foo getFoo() {
return this.foo;
}
}
Given the following Spring configuration:
@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);
}
}
For completeness here is a simple unit test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {SpringContext.class})
public class SpringAppTests {
@Autowired
private FooService fooService;
@Test
public void testGetName() {
Assert.assertEquals("foo", fooService.getFoo().getName());
}
}
Then loading the context will throw a NoSuchBeanDefinitionException (Foo).
Can anyone see anything wrong/missing on this example, or provide me a reason for that?
Thank you! Christian
In addition to the other answers:
The problem is that spring does not take the required=false
into account when injecting parameters. See ConstructorResolver
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
The second argument is always true
:
public DependencyDescriptor(MethodParameter methodParameter, boolean required)
EDIT: Spring uses the ConstructorResolver
for
"real" constuctor injection
@Autowired(required=false) // required=false WILL NOT WORK
public FooService(Foo foo){
...
}
factory methods
@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);
}
Thus in both cases the required
attribute is ignored.
You have your syntax wrong. The @Autowired(required = false)
would need to be relating to the Foo
.
For example:
@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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With