如何在构造函数参数中使用Spring Prototype Bean?

时间:2019-01-25 22:58:10

标签: java spring design-patterns lombok

我确实使用Spring和Lombok。
如果没有原型bean,我们必须传递目标类所需的依赖项。
我们如何将bean标记为原型并正确处理依赖的bean和构造函数参数?

选项1 -没有原型bean

@Component @RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class Consumer {
  private final SomeDependency iDontNeed; // Consumer class doesn't need
  private final SomeDependency2 iDontNeed2;

  public void method() {
    new Processor("some random per request data", iDontNeed, iDontNeed2);
  }
....
@Value @RequiredArgsConstructor
public class Processor {
  private final String perRequestInputData;
  private final SomeDependency iReallyNeed;
  private final SomeDependency2 iReallyNeed2;
}

选项2 -原型bean

@Component @RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class Consumer {
  private final Provider<Processor> processorProvider;

  public void method() {
    Processor p = processorProvider.get();
    p.initializeWith("some random per request data");
  }
....
@Component @Scope("prototype") 
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class Processor {
  private final SomeDependency iReallyNeed;
  private final SomeDependency2 iReallyNeed2;

  private String perRequestInputData; //wish I was final
  private boolean initialized; //wish I was not needed

  public void initializeWith(String perRequestInputData) {
    Preconditions.checkState(!initialized);
    this.perRequestInputData = perRequestInputData
    initialized = true;
  }
}

1 个答案:

答案 0 :(得分:2)

我的评论:

选项1:

它干净简单。并非每个类都需要声明为Spring bean。如果一个类足够简单,并且不使用任何Spring功能(例如@Cache@Tranascational等),那么KISS可以这样做,而不必将其声明为Spring bean并手动创建。 Consumer就像Main类来驱动逻辑一样,因此SomeDependency在某种意义上也需要Consumer,因为它需要它们来驱动创建{{ 1}}。

选项2:

同意。不太好,因为与选项1(我们只需要通过构造函数创建)相比,我们需要单独的调用和额外的“初始化”属性来确保正确创建了Processor。但是Processor是一个Spring bean,因此我们可以很容易地将Spring功能应用到它。

我们还有其他选择吗?

我的替代方法是将工厂模式与Processor@Configuration结合使用,以兼得两全:

首先定义一个工厂:

@Bean

然后在消费者中:

@Configuration
public class ProcessorFactory {

     @Autowired
     private final SomeDependency dep1; 

     @Autowired
     private final SomeDependency2 dep2;

     @Bean
     @Scope("prototype") 
     public void createProcessor(String requestData) {
        return new Processor(requestData, dep1, dep2);
    }
}