在创建具有不同数据的 bean 列表时,相同数据应用于所有相同类型的 Bean
Same Data applied across all Beans of same type while creating a list of beans with different data
我的用例是创建一个 Bean 列表 "B",每个 Bean 都有一个不同的依赖 bean 实例 "C"。
@Component("a")
public class A{
List<B> bPool = new ArrayList<>();
private ApplicationContext appContext;
@Autowired
A(ApplicationContext appContext){
this.appContext = appContext;
}
@PostConstruct
public void init(){
for(int i=0; i<POOL_SIZE; i++){
bPool.add((B) appContext.getBean("b"));
}
}
//code for multi-threading, which uses beans from the list bPool.
//I iterate the list, launch multiple threads,
//pass different data to each thread and combine results.
List<CompletableFuture> multiThreads = new ArrayList<>();
Iterator it = bPool.iterator();
for(Data d : listOfSomeData){ //same size for listOfSomeData and bPool
CompletableFuture var = CompletableFuture.supplyAsync(() -> {
B curr = (B) it.next()
curr.someMethodInB(d);
});
multiThreads.add(var);
}
multiThreads.forEach(cf -> cf.join());
}
@Component("b")
@Scope("prototype")
public class B{
//Service class - has some dependencies, like C below
private C c;
private ApplicationContext appContext;
@Autowired
B(ApplicationContext appContext){
this.appContext = appContext;
}
@PostConstruct
public void init(){
c = (C) appContext.getBean("c");
}
}
@Component("c")
@Scope("prototype")
public class C{
//this class holds some data and does some processing on it,
//I want this to be different for different instances in different threads.
}
在 bPool 中创建 B 列表时,在构造时(我通过在 post-construct 中打印检查),分别为每个 B 设置了不同的 C 实例。
但是,当稍后使用同一池中的 B 实例时,所有 B 实例都具有相同的 C 实例。
它们都有 C 实例,该实例设置为 bPool 的最后创建的 B 元素。
我是 springboot 的新手,无法理解这种行为。任何帮助表示赞赏。谢谢
仍然不确定是什么导致了这个问题。然而,一种不同的方法解决了我的用例。
我继续使用 spring 本身提供的异步功能。
在您的主 class 中,添加 @EnableAsync 注释并创建后台线程池 运行。
@SpringBootApplication
@EnableAsync
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args).close();
}
@Bean
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("ThreadName-");
executor.initialize();
return executor;
}
}
使用 public 方法创建一个新的 class 方法,@Async 注释包含我们想要在后台 运行 的繁重代码。此方法需要 public 并且必须在不同的 class 中才能使代理工作。我们无法在将调用它的同一个 class 中创建此异步方法。
@Component
public class MyAsyncService {
@Async
public CompletableFuture<ResultClass> myAsyncMethod(String params){
//do some heavy tasks here
return CompletableFuture.completedFuture(instanceOfResultClass);
}
}
使用来自调用方 class 的异步方法调用上述 class。
@Component
public class CallerService{
private MyAsyncService myAsyncService;
@Autowired
public CallerService(MyAsyncService myAsyncService){
this.myAsyncService = myAsyncService;
}
public void myMethod(){
CompletableFuture<ResultClass> result1 = myService.findUser("PivotalSoftware");
CompletableFuture<ResultClass> result2 = gitHubLookupService.findUser("CloudFoundry");
CompletableFuture.allOf(result1, result2).join();
ResultClass finalResult1 = result1.get();
ResultClass finalResult2 = result2.get();
}
}
我的用例是创建一个 Bean 列表 "B",每个 Bean 都有一个不同的依赖 bean 实例 "C"。
@Component("a")
public class A{
List<B> bPool = new ArrayList<>();
private ApplicationContext appContext;
@Autowired
A(ApplicationContext appContext){
this.appContext = appContext;
}
@PostConstruct
public void init(){
for(int i=0; i<POOL_SIZE; i++){
bPool.add((B) appContext.getBean("b"));
}
}
//code for multi-threading, which uses beans from the list bPool.
//I iterate the list, launch multiple threads,
//pass different data to each thread and combine results.
List<CompletableFuture> multiThreads = new ArrayList<>();
Iterator it = bPool.iterator();
for(Data d : listOfSomeData){ //same size for listOfSomeData and bPool
CompletableFuture var = CompletableFuture.supplyAsync(() -> {
B curr = (B) it.next()
curr.someMethodInB(d);
});
multiThreads.add(var);
}
multiThreads.forEach(cf -> cf.join());
}
@Component("b")
@Scope("prototype")
public class B{
//Service class - has some dependencies, like C below
private C c;
private ApplicationContext appContext;
@Autowired
B(ApplicationContext appContext){
this.appContext = appContext;
}
@PostConstruct
public void init(){
c = (C) appContext.getBean("c");
}
}
@Component("c")
@Scope("prototype")
public class C{
//this class holds some data and does some processing on it,
//I want this to be different for different instances in different threads.
}
在 bPool 中创建 B 列表时,在构造时(我通过在 post-construct 中打印检查),分别为每个 B 设置了不同的 C 实例。
但是,当稍后使用同一池中的 B 实例时,所有 B 实例都具有相同的 C 实例。
它们都有 C 实例,该实例设置为 bPool 的最后创建的 B 元素。
我是 springboot 的新手,无法理解这种行为。任何帮助表示赞赏。谢谢
仍然不确定是什么导致了这个问题。然而,一种不同的方法解决了我的用例。
我继续使用 spring 本身提供的异步功能。
在您的主 class 中,添加 @EnableAsync 注释并创建后台线程池 运行。
@SpringBootApplication @EnableAsync public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args).close(); } @Bean public Executor asyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(2); executor.setMaxPoolSize(2); executor.setQueueCapacity(500); executor.setThreadNamePrefix("ThreadName-"); executor.initialize(); return executor; } }
使用 public 方法创建一个新的 class 方法,@Async 注释包含我们想要在后台 运行 的繁重代码。此方法需要 public 并且必须在不同的 class 中才能使代理工作。我们无法在将调用它的同一个 class 中创建此异步方法。
@Component public class MyAsyncService { @Async public CompletableFuture<ResultClass> myAsyncMethod(String params){ //do some heavy tasks here return CompletableFuture.completedFuture(instanceOfResultClass); } }
使用来自调用方 class 的异步方法调用上述 class。
@Component public class CallerService{ private MyAsyncService myAsyncService; @Autowired public CallerService(MyAsyncService myAsyncService){ this.myAsyncService = myAsyncService; } public void myMethod(){ CompletableFuture<ResultClass> result1 = myService.findUser("PivotalSoftware"); CompletableFuture<ResultClass> result2 = gitHubLookupService.findUser("CloudFoundry"); CompletableFuture.allOf(result1, result2).join(); ResultClass finalResult1 = result1.get(); ResultClass finalResult2 = result2.get(); } }