java 为什么@Autowired(required=false) 在@Configuration bean 上不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25157293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 07:28:19  来源:igfitidea点击:

Why @Autowired(required=false) do not work on @Configuration beans?

javaspringconfigurationautowired

提问by Christian Sisti

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:

鉴于以下 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);
    }
}

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

然后加载上下文将抛出 NoSuchBeanDefinitionException (Foo)。

Can anyone see anything wrong/missing on this example, or provide me a reason for that?

任何人都可以在这个例子中看到任何错误/遗漏的地方,或者给我一个理由吗?

Thank you! Christian

谢谢!基督教

回答by René Link

In addition to the other answers:

除了其他答案:

The problem is that spring does not take the required=falseinto account when injecting parameters. See ConstructorResolver

问题是springrequired=false在注入参数时没有考虑。看ConstructorResolver

return this.beanFactory.resolveDependency(
        new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);

The second argument is always true:

第二个参数总是true

public DependencyDescriptor(MethodParameter methodParameter, boolean required)

public DependencyDescriptor(MethodParameter methodParameter, boolean required)

EDIT:Spring uses the ConstructorResolverfor

编辑:Spring 使用ConstructorResolverfor

  • "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);
    }
    
  • “真正的”构造函数注入

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

Thus in both cases the requiredattribute is ignored.

因此,在这两种情况下,该required属性都被忽略。

回答by Ben Green

You have your syntax wrong. The @Autowired(required = false)would need to be relating to the Foo.

你的语法错误。在@Autowired(required = false)将需要有关的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);
    }
}

回答by Ralph

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);
    }
}