【问题标题】:Spring Boot- Autowiring interface implemented by different beansSpring Boot——不同bean实现的自动装配接口
【发布时间】:2020-01-22 22:24:06
【问题描述】:

我有多个带有@Component 实现通用接口的bean。

我有一个类,我使用这些 bean 中的方法。我没有单独自动装配每个 bean,而是想办法将接口自动装配为一个列表。

但是当我只是自动装配接口时,如何调用不同 bean 的方法。

public interface Generic {
}

@Component
public class A implements Generic{
.....
public void test{
}

}

@Component
public class B implements Generic{
.....
public void read{}

}


@component class C {

@Autowired
List <Generic> mylist;  // type of list is Generic

现在我需要从 B 访问读取并从 A 进行测试

【问题讨论】:

  • 使用read()test()方法的唯一方法是将它们转换为相关类(AB),然后调用该方法。
  • @Saranya_R 你有调用“read()”和“test()”的顺序吗?

标签: spring list spring-boot interface autowired


【解决方案1】:

对于您的新问题,您可以这样做,但我认为最好使用 2 个单独的列表而不是 instanceOf。

public interface Generic { }

public interface GenericTestable extends Generic { 
    void test()
}

public interface GenericReader extends Generic { 
    void read()
}

@Component
public class A implements GenericTestable { 
   public void test() { }
}

@Component
public class B implements GenericReader { 
   public void read() { } 
}

@Component
public class C {

   private final List<Generic> genericItems;

   @Autowired
   public C(List<Generic> genericItems) {
       this.genericItems = genericItems;
   }

   public void callThem() {
       this.genericItems.forEach(this::callMethodOnSpecificType);
   }

   private void callMethodOnSpecificType(Generic genericItem) {
       if (genericItem instanceof GenericTestable) {
           ((GenericTestable) genericItem).test();
       } else if (genericItem instanceof GenericReader) {
           ((GenericReader) genericItem).read();
       }
   }
}

但我认为这样的方法是更好的方法。更干净,更快的代码。删除 Generic 接口并仅使用 2 个单独的接口。

public class BetterC {

    private final List<GenericTestable> genericTestables;
    private final List<GenericReader> genericReaders;

    @Autowired
    public BetterC(List<GenericTestable> genericTestables, List<GenericReader> genericReaders) {
        this.genericTestables = genericTestables;
        this.genericReaders = genericReaders;
    }

    public void callTestables() {
        this.genericTestables.forEach(GenericTestable::test);
    }

    public void callReaders() {
        this.genericReaders.forEach(GenericReader::read);
    }
}

【讨论】:

  • 我采用了第一种方法。但是在这两种方法中,我如何在 C 类中使用 A.test 和 B.read。
  • 我看到您更改了原始代码并将read()write()添加到特定类中。如果这是最好的策略,这取决于你的代码的其余部分。接口现在有点奇怪,因为问题是它们是否属于同一类型。
  • 现在使用它并调用read()test()的唯一方法是遍历列表并使用instanceOf检查特定类型,然后将其转换为特定类型并调用@987654327 @ 或 test()。这不是一个好主意。如果您只有这 2 个对象,最好删除接口并自行自动连接它们。如果您有多个,您可以选择使用 2 个不同的界面,比如 GenericReaderGenericWriter 并使用 2 个列表(List&lt;GenericReader&gt; readersList&lt;GenericWriter&gt; writers
  • 其实我添加接口只是为了以一种简单的方式实现自动装配。我有大约 10 个类,基本上它们是 10 个不同的报告,每个报告以不同的方式使用不同的参数实现一个生成方法。所以我不能在界面中生成方法。我想在每个报表类中实现接口,然后自动装配接口。但是我需要从报告类中调用方法来生成每个报告。我不明白这是否可以真正实现,所以我转移到应用程序上下文并从上下文中获取 bean。
  • 示例根据新的/修改后的问题进行了更改。
【解决方案2】:

使用通用接口路由呼叫怎么样?

来自 java-doc api:Ordered

Ordered 是一个可以由对象实现的接口 可以订购,例如在 Collection 中。实际订单可以 解释为优先级,第一个对象(最低 order value) 具有最高优先级。

import org.springframework.core.Ordered;

public interface Generic extends Ordered {
    void call();
}
----
@Component
public class A implements Generic {

    @Override
    public int getOrder() {
        return 2;
    }

    @Override
    public void call() {
        test();
    }

    public void test() {
        System.out.println("Call test()");
    }
}
----
@Component
public class B implements Generic {

    @Override
    public int getOrder() {
        return 1;
    }

    @Override
    public void call() {
        read();
    }

    public void read() {
        System.out.println("call read()");
    }
}
----
@Component
public class C {

    List<Generic> list;

    public C(List<Generic> list) {
        this.list = list;
    }

    public void testMethod() {
        for(Generic g: list) {
            g.call();
        }
    }
}

【讨论】:

    【解决方案3】:

    在你的实现中试试这个

    @Component
    @Qualifer("a")
    public class A implements Generic{ ..... public void test(){ }}
    
    @Component
    @Qualifer("b")
    public class B implements Generic{ ..... public void read(){ }}
    
    @component 
    public class C {
    
        @Autowired
        Generic a;
    
        @Autowired
        Generic b;
    
        ... call respective methods
    
    }
    

    【讨论】:

    • 我不想对所有 bean 使用 @Autowired。只需自动装配接口就可以做到这一点。但我不知道如何调用我的方法。
    猜你喜欢
    • 2019-01-16
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多