【问题标题】:Java Bean Composite injectionJava Bean 复合注入
【发布时间】:2016-08-22 02:37:42
【问题描述】:

我有一个界面

public interface Abstraction { 
    void execute();
}

我已经构建了一个复合实现,并希望将此对象注册为 bean,@Named

@Named
public class Composite implements Abstraction {
    private List<Abstraction> list;

    @Inject
    public Composite(List<Abstraction> list) {
        this.list = list;
    }

    public void execute() { 
        list.forEach(Abstraction::execute);
    }
}

如何设置它,以便将抽象的实现集正确地注入到上面的 Composite 中?我将拥有另一个将抽象作为依赖项的对象,我希望它接收上面的@Named Composite,并将下面的 2 个实现注入到 ctor 中。

public class Implementation1 implements Abstraction {
    public void execute() { }
}

public class Implementation2 implements Abstraction {
    public void execute() { }
}

【问题讨论】:

  • 总是两个吗?只需按名称分别注入即可。
  • @Pillar 这是我的特殊情况,我可以这样做,但不知道怎么做,因为我不能在每个实现上加上 Named 注释。抱歉,我是 Java bean 世界的新手。

标签: java spring dependency-injection spring-boot javabeans


【解决方案1】:

如果您为每个实现创建一个 bean,您的示例将开箱即用。例如,使用@Named@Component 注释您的实现并将它们标记为扫描(组件扫描它们的包)

@Configuration
@ComponentScan
public class StackOverflow {
    public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(StackOverflow.class);
        System.out.println(ctx.getBean(Composite.class).list);
    }
}

interface Abstraction {
    void execute();
}

@Named
class Composite implements Abstraction {
    List<Abstraction> list;

    @Inject
    public Composite(List<Abstraction> list) {
        this.list = list;
    }

    public void execute() {
        list.forEach(Abstraction::execute);
    }
}

@Named
class Implementation1 implements Abstraction {
    public void execute() {
    }
}

@Named
class Implementation2 implements Abstraction {
    public void execute() {
    }
}

Composite 的列表将包含这两种实现。

另外,由于您只有两个实现,您可以命名它们的 bean 并分别注入它们。例如

@Component("one")
class Implementation1 implements Abstraction {
    public void execute() {
    }
}

@Component("two")
class Implementation2 implements Abstraction {
    public void execute() {
    }
}

并将它们注入Composite

List<Abstraction> list = new ArrayList<>(2);

@Inject
public Composite(@Qualifier("one") Abstraction one, @Qualifier("two") Abstraction two) {
    list.add(one);
    list.add(two);
}

我建议这个解决方案只是因为Abstraction bean 的初始化顺序可能会弄乱您的上下文初始化。例如,如果Implementation1 以某种方式依赖于Composite 的初始化,则上下文会抱怨。这很少见,您可以通过其他方式控制它。不过,在这种情况下,明确说明 bean 可能会更清楚。

【讨论】:

  • 你的第一个场景适用于我的情况,我不在乎为我的组合填充抽象列表的顺序。但是我看到,当创建复合 bean 时,它实际上有其他 2 个实现就好了,但是当尝试创建另一个依赖于 Abstraction 的 bean 时,它如何知道它应该注入复合?在这种情况下我得到一个错误:expected single matching bean but found 3: implementation2,composite,implementation1
  • @JonErickson 您需要使用名称对其进行限定,并在注入点使用该名称。或者,定义一个单独的接口,它是Abstraction 的子类型(如CompositieAbstract),让Composite 实现它,然后注入。
  • 知道了,我在组合中添加了Named("composite") 注释,然后在另一个对象的构造函数参数中添加了Qualifier("composite") 注释。感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 2011-12-05
  • 1970-01-01
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 1970-01-01
相关资源
最近更新 更多