在创建具有不同数据的bean列表时,相同数据应用于所有相同类型的Bean

时间:2018-06-01 07:26:07

标签: java spring spring-boot javabeans

我的用例是创建一个Bean“B”列表,每个都有一个从属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列表时,在构建时(我在后构造中通过打印检查),分别为每个B设置了不同的C实例。

但是,稍后在同一个池中使用B实例时,所有B实例都具有相同的C实例。

它们都有C实例,它被设置为bPool的最后一个创建的B元素。

我是springboot的新手,无法理解这种行为。任何帮助赞赏。感谢

1 个答案:

答案 0 :(得分:0)

仍然不确定导致问题的原因。然而,一种不同的方法解决了我的用例。

我继续使用spring本身提供的Async功能。

参考:documentation link

  1. 在主类中,添加@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;
    }
    }
    
  2. 使用带有@Async注释的公共方法创建一个新类,其中包含我们想要在后台运行的重代码。此方法需要是公共的,并且必须在不同的类中才能进行代理工作。我们无法在调用它的同一个类中创建这个异步方法。

    @Component
    public class MyAsyncService {
    
        @Async
        public CompletableFuture<ResultClass> myAsyncMethod(String params){
            //do some heavy tasks here
            return CompletableFuture.completedFuture(instanceOfResultClass);
        }
    }
    
    1. 使用来自调用者类的异步方法调用上述类。

      @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();
          }
      }