当前位置: 首页 > 知识库问答 >
问题:

如何将Spring原型Beans与构造函数参数一起使用?[关闭]

储嘉悦
2023-03-14

想改进这个问题吗?更新问题,以便可以通过编辑这篇文章来回答事实和引文。

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

选项1 -没有原型beans

@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 - 原型豆

@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个答案

蔡默
2023-03-14

我的评论:

选项1:

它干净简单。并非每个类都需要声明为Springbean。如果一个类足够简单,不使用任何Spring特性(例如@Cache@Tranasional等),那么KISS可以不将其声明为Springbean并手动创建它。Consumer就像驱动逻辑的Main类一样,所以我会说SomeDependency在某种意义上也是Consumer所需要的,因为它需要它们来驱动创建Processor的逻辑。

选项2:

同意你的观点。与选项1相比,我们需要单独的调用和额外的“初始化”属性来确保处理器被正确创建,而我们只需要通过构造函数创建它。但是处理器是一个Spring bean,所以我们可以很容易地将Spring功能应用于它。

我们有其他选择吗?

我的替代方案是使用工厂模式与@配置@Bean来两全其美:

首先定义工厂:

@Configuration
public class ProcessorFactory {

     @Autowired
     private final SomeDependency dep1; 

     @Autowired
     private final SomeDependency2 dep2;

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

然后在消费者中:

@Component
public class Consumer {

     @Autowired 
     private final ProcessorFactory processorFactory;


      public void method() {
        Processor p = processorFactory.createProcessor("some random per request data");
        p.blablbaba();
      }
}

注意:< code >处理器上的< code > @ Bean(autowire candidate = false) @ Bean是必需的。否则,Spring会在启动时试图找到一个String类型的bean来创建一个处理器。由于没有字符串类型的bean,它将抛出异常。将< code>autowireCandidate设置为false可以禁用Spring create it。毕竟,我们将从< code>ProcessorFactory手动创建它

 类似资料:
  • 我分配给类的属性是: 我需要设置ISSOLD,并敦促其设置为false。这就是我创建默认构造函数的原因。但是我使用Builder()来设置类字段,并且在某个地方使用getter/setter来设置属性。 我的要求是将isPurpressed/IsSoldOut设置为True/False,但不能为NULL。 请指导我如何才能做到这一点。

  • 问题内容: 这是我尝试在其上使用该函数的循环: 有办法吗?如果不是参数,那将是微不足道的,但是我不确定如何处理。 问题答案: 用途: 创建一个新的可调用对象,除了传递给该新的可调用对象的内容之外,该参数还将对包装的函数应用所有参数(包括关键字参数)。

  • 本文向大家介绍我们如何在Java中将枚举类型与构造函数一起使用?,包括了我们如何在Java中将枚举类型与构造函数一起使用?的使用技巧和注意事项,需要的朋友参考一下 枚举类型可以具有一个私有的构造函数,该构造函数可用于初始化实例字段。  EnumDemo类演示了这一点。它具有带有四个常量的Food枚举类型:HAMBURGER,FRIES,HOTDOG和ARTICHOKE。请注意,括号后的每个常数值之

  • 我试图弄清楚如何在CDI中使用构造函数注入,其中一个参数是JNDI查找。 用正常的打野,我可以做到以下几点: 如何指定参数是通过JNDI查找检索的bean?在哪里指定JNDI名称?

  • 我有一个使用构造函数表达式的查询。在大多数情况下,它是工作的,但是我想减少数据库上的查询数量。所以我尝试了FETCH和@EntityGgraph,但是我得到了 org.springframework.dao.InvalidDataAccessResourceUsageException:查询指定的联接提取,但提取关联的所有者不在选择列表中[FromElement{explicit,不是集合联接,提

  • 假设我有对象:bob1,cob2。我想为类B和C建立一个析构函数,但我不确定如何销毁B.BB和C.CC以及如何访问它们。还有,有没有办法让我做到这一点,而不让类成为a类的朋友?