Why is @Autowired (required = false) not working in @Configuration beans?

Explain 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, there is a simple unit test here:

@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) exception.

Can someone see something wrong or not in this example or show me the reason for this?

Thank! Christian

+4
source share
3 answers

In addition to other answers:

The problem is that spring is not taken into account required=falsewhen entering parameters. Cm.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 ConstructorResolverfor

  • ""

    @Autowired(required=false) // required=false WILL NOT WORK
    public FooService(Foo foo){
        ...
    }
    
  • factory

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

+4

Try

@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);
    }
}
+2

You have the wrong syntax. @Autowired(required = false)must be associated with Foo.

For instance:

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

All Articles