spring 在for循环中获取autowired类bean的不同示例

hc2pp10m  于 2023-11-16  发布在  Spring
关注(0)|答案(1)|浏览(115)

我是Sping Boot 的新手,正在学习autowire annotation、依赖注入和单元测试
我在Sping Boot 中有一个代码,如下所示

@Component
class A {
  public void classAMethod() {
    for(int i=0; i<10; i++) {
      B b = new B(dynamicStirngValue,dynamicIntValue, i);
      Object xyz = b.execute();
    }
  }
}

@Component
@Scope("prototype")
class B {

  public B(String str1, int int1, int int2) {
    // setting up the passed parameters
  }
  public Object execute() {
    // some code to use the class variables
  }
}

字符串
我想用代码实现三件事:
1.与其使用new关键字创建B的对象,我希望它使用@autowired(Departmentinjection),这将有助于我在单元测试时模拟B并模拟execute()方法的返回。
1.由于B有一个参数化的构造函数,我希望能够通过传递参数来获取bean,参数值将是动态的,即对于循环的每次迭代,传递的值都是不同的。我在网上找到的示例使用的是属性文件中的值。

  1. classAMethod()是在多线程环境中被调用的,这就是为什么在for循环中我每次都要创建一个B类的新示例,以避免并发问题,所以我想使用autowire来获得一个B类的新示例。我不能在B内部使用synchronized关键字,因为它内部执行了很多操作,因此每次创建一个新的示例比锁定和解锁代码块更简单,并且它将导致性能问题的减少,因为只有一个线程可以访问该代码块。
    你能为这个场景提供一个例子吗?或者有其他方法。
    我想这样做有两个原因:
    1.单元测试
    1.使应用程序完全使用Sping Boot 概念(DI)并避免new关键字
    我可以通过构造函数mocking来进行单元测试,但这种方法的问题是我们需要做@PrepareForTest(A.class),它有自己的问题,比如代码覆盖率显示为0%。
    谢谢
eanckbw9

eanckbw91#

让我们看看如何解决这个问题:

  • 配置一个bean来提供dynamicStirngValuedynamicIntValue,我们可以使用CopyOnWriteArrayList来使用线程安全列表
@Configuration
public class ParamsKeyVal  {
    @Bean
    public List<HashMap<String, Integer>>  getParams() {
        HashMap<String, Integer> params = new HashMap<>();
        List<HashMap<String, Integer>> list = new CopyOnWriteArrayList<>();

        list.add(Map.of("key1", 10));
        list.add(Map.of("key2", 13));

        // this params can found form other source like properties file/database
        return list;
    }
}

字符串

  • 更新组件A,使其可以测试友好
@Component
class A {
    private final List<HashMap<String, Integer>> params;
    private final B b;

    @Autowired
    public A(List<HashMap<String, Integer>> params, B b) {

        this.params = params;
        this.b = b;
    }

    public void classAMethod() {
        for(int i=0; i<params.size(); i++) {

            HashMap<String, Integer> entrySet = params.get(i);
            String dynamicStirngValue = null;
            Integer dynamicIntValue = null;
            for (Map.Entry<String, Integer> entry : entrySet) {

                dynamicStirngValue =  entry.getKey();
                dynamicIntValue = entry.getValue();
                break;
            }

            b.setDynamicStirngValue(dynamicStirngValue);
            b.setDynamicIntValue(dynamicIntValue);
            b.setDynamicInt(i);

            Object xyz = b.execute();
        }
    }

}

  • 更新无参数构造函数的组件B
@Component
@Scope("prototype")
class B {

    public B() {

    }
    public B(String str1, int int1, int int2) {
        // setting up the passed parameters
    }
    public Object execute() {
        // some code to use the class variables
    }
}

相关问题