繁体   English   中英

按接口自动装配 bean,但在注入时排除特定 bean

[英]Autowire beans by interface but exclude specific bean at injection time

我目前正在注入一个 Spring @Component列表,它们都实现了相同的接口。 这很好用,但是我想将这个相同的列表注入到该列表中的一个 bean 的实例中,这样我就可以对该列表中的所有其他 bean 采取行动。 我看不到如何从该注入中排除特定的 bean,我可以在注入后过滤列表,但这当然会在启动时导致 Spring 循环依赖异常。 我的问题是我可以在注入时告诉 spring 从 bean 列表中排除注入的 class 吗?

public interface Foo {
    String doSomething();
}
@Component
public class Foo1 implements Foo {

    private final List<Foo> foos;

    public Sample(final List<Foo> foos) {
        //Don't include Foo1
        this.foos = foos;
    }

    public String doSomething() {
        foos.forEach(foo -> foo.doSomething());
        return "aString";
    }
}

@Component
public class Foo2 implements Foo {

    private final List<Foo> foos;

    public Sample(final List<Foo> foos) {
        //Don't include Foo2
        this.foos = foos;
    }

    public String doSomething() {
        foos.forEach(foo -> foo.doSomething());
        return "anotherString";
    }
}
@Component
public class Foo3 implements Foo {
//and so on

我同意@robertobatts 的观点,它看起来确实像一个反模式,你应该避免它。 如果您可以澄清问题背景,也许我们可以帮助您以更好的方法来实现您想要实现的目标!

这个解决方案几乎是一个 hack,除非真的有必要,否则我不建议使用它。 您可以在@Configuration class 中将其定义为 @Configuration Foo2 ,而不是将其声明为组件,方法是将ListableBeanFactory作为 bean 定义方法中的参数注入,然后使用它的getBeansOfType方法过滤掉您实际需要实例化Foo2 bean 的Foo实现。

所以你的 Foo2 class 看起来像

public class Foo2 implements Foo {

    private final List<Foo> foos;

    public Foo2(final List<Foo> foos) {
        this.foos = foos;
    }

    public String doSomething() {
        foos.forEach(foo -> foo.doSomething());
        return "anotherString";
    }
}

并且配置 class 看起来像

@Configuration
public class MyConfiguration {

    @Bean
    Foo2 foo2(ListableBeanFactory bf) {
        final Map<String, Foo> fooBeans = bf.getBeansOfType(Foo.class);
        List<Foo> foos = // filter out what you don't need from fooBeans
        return new Foo2(foos);
    }

}

您可以在doSomething方法中查找所有Foo类型的 bean,然后排除当前的,而不是在构造函数中注入列表。 要查找,请使用BeanFactoryUtils中的任何方法,例如beanNamesForTypeIncludingAncestors ,然后排除foo1 ,这是 class Foo1的 bean 名称。 查找甚至可以编码为接口Foo中的默认方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM