提问人:Akshay Borse 提问时间:11/15/2023 更新时间:11/15/2023 访问量:26
在 for 循环中获取 autowired 类 bean 的不同实例
Get different instance of autowired class bean in for loop
问:
我是Spring Boot的新手,学习autowire注解,依赖注入和单元测试
我在Spring 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
}
}
我想用代码实现 3 件事:
与其使用我希望它使用 @autowired(依赖注入)的新关键字创建 B 的对象,这将是有帮助的,这样我就可以在单元测试时模拟 B 并模拟 execute() 方法的返回。
由于 B 有一个参数化构造函数,我希望能够通过传递参数来获取 bean,参数值将是动态的,即对于循环的每次迭代,传递的值都会有所不同。我在网上找到的示例使用属性文件中的值。
classAMethod() 是在多线程环境中调用的,这就是为什么在 for 循环中我每次都创建一个类 B 的新实例,以避免并发问题,所以使用 autowire 我想获取类 B 的新实例。我不能在 B 中使用 synchronized 关键字,因为它在内部执行大量操作,因此每次创建新实例都比锁定和解锁代码块更简单,并且会导致性能问题降低,因为只有一个线程可以访问该代码块。
您能为这种情况提供一个示例吗?或者有没有其他方法。
我想这样做有两个原因:
- 单元测试
- 完全使用 Spring Boot 概念 (DI) 制作应用程序并避免使用新关键字
我可以通过构造函数模拟来进行单元测试,但这种方法的问题在于我们需要执行 @PrepareForTest(A.class),它有自己的问题,例如代码覆盖率显示为 0%。
谢谢
答:
1赞
Sahab
11/15/2023
#1
让我们看看我们如何解决这个问题:
- 配置一个 bean 来供应,我们可以使用胎面安全列表使用
dynamicStirngValue
dynamicIntValue
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
}
}
评论
applicationcontext.getBean
new