How to use Pooled Spring beans instead of Singleton ones?

前端 未结 5 1224
后悔当初
后悔当初 2021-01-14 16:45

For efficiency reasons, I am interested in limiting the number of threads that simultaneously uses the beans of the Spring application context (I don\'t want an unli

5条回答
  •  清酒与你
    2021-01-14 17:31

    I did it using Annotations based configuration:

    1. I did create my BusinessObject class as a POJO and annotate it this way:

      @Component("businessObject")
      @Scope("prototype")
      public class BusinessObject { ... }
      

      I gave it a specific name and did mark it as prototype so that Spring doesn't create a singleton instance for it; every time the bean is required, Spring would create a new instance.

    2. In my @Configuration class (or in the @SpringBootApplication class, if using Spring Boot) I created a CommonsPool2TargetSource instance to hold BusinessObject instances:

      @Bean
      public CommonsPool2TargetSource pooledTargetSource() {
          final CommonsPool2TargetSource commonsPoolTargetSource = new CommonsPool2TargetSource();
          commonsPoolTargetSource.setTargetBeanName("businessObject");
          commonsPoolTargetSource.setTargetClass(BusinessObject.class);
          commonsPoolTargetSource.setMaxSize(maxPoolSize);
          return commonsPoolTargetSource;
      }
      

      Here I'm indicating that the pool will hold BusinessObject instances. Notice that my maxPoolSize=? value is set with the max number of BusinessObject instances I want to hold in the pool.

    3. Finally, I did access my pooled instances this way:

      @Autowired
      private CommonsPool2TargetSource pooledTargetSource;
      
      void someMethod() {
          // First I retrieve one pooled BusinessObject instance
          BusinessObject businessObject = (BusinessObject)pooledTargetSource.getTarget();
      
          try {
              // Second, I do some logic using the BusinessObject instance gotten
          } catch (SomePossibleException e) {
              // Catch and handle any potential error, if any
          } finally {
      
              // Finally, after executing my business logic
              // I release the BusinessObject instance so that it can be reused
              pooledTargetSource.releaseTarget(businessObject);
          }
      }
      

      It is very important to always make sure to release the BusinessObject borrowed from the pool, without mattering if the business logic did finish successfully or with error. Otherwise the pool could get empty with all the instances being borrowed and never released and any further requests for instances will block forever.

提交回复
热议问题