带有运行时构造函数参数的 Spring bean

新手上路,请多包涵

我想在 Spring Java 配置 中创建一个 Spring bean,并在运行时传递一些构造函数参数。我创建了以下 Java 配置,其中有一个 bean fixedLengthReport 需要构造函数中的一些参数。

 @Configuration
public class AppConfig {

    @Autowrire
    Dao dao;

    @Bean
    @Scope(value = "prototype")
    **//SourceSystem can change at runtime**
    public FixedLengthReport fixedLengthReport(String sourceSystem) {
         return new TdctFixedLengthReport(sourceSystem, dao);
    }
}

但是我收到错误消息,因为没有找到 bean, 所以 sourceSystem 无法连接。如何使用运行时构造函数参数创建 bean?

我正在使用 Spring 4.2

原文由 suraj bahl 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 983
2 个回答

您可以将原型 bean 与 BeanFactory 一起使用。

 @Configuration
public class AppConfig {

   @Autowired
   Dao dao;

   @Bean
   @Scope(value = "prototype")
   public FixedLengthReport fixedLengthReport(String sourceSystem) {
       return new TdctFixedLengthReport(sourceSystem, dao);
   }
}

@Scope(value = "prototype") 意味着 Spring 不会在开始时立即实例化 bean,但稍后会根据需要进行实例化。现在,要自定义原型 bean 的实例,您必须执行以下操作。

 @Controller
public class ExampleController{

   @Autowired
   private BeanFactory beanFactory;

   @RequestMapping("/")
   public String exampleMethod(){
      TdctFixedLengthReport report =
         beanFactory.getBean(TdctFixedLengthReport.class, "sourceSystem");
   }
}

注意,因为你的 bean 不能在启动时实例化,所以你不能直接自动装配你的 bean;否则 Spring 将尝试实例化 bean 本身。这种用法会导致错误。

 @Controller
public class ExampleController{

   //next declaration will cause ERROR
   @Autowired
   private TdctFixedLengthReport report;

}

原文由 Ken Bekov 发布,翻译遵循 CC BY-SA 4.0 许可协议

这可以通过在 Spring 4.3 中引入的 Spring 的 ObjectProvider<> 类来实现。有关更多详细信息,请参阅 Spring 的 文档

要点是为要提供的对象定义 bean 工厂方法,将 ObjectProvider<> 注入您的消费者并创建要提供的对象的新实例。

 public class Pair
{
    private String left;
    private String right;

    public Pair(String left, String right)
    {
        this.left = left;
        this.right = right;
    }

    public String getLeft()
    {
        return left;
    }

    public String getRight()
    {
        return right;
    }
}

@Configuration
public class MyConfig
{
    @Bean
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public Pair pair(String left, String right)
    {
        return new Pair(left, right);
    }
}

@Component
public class MyConsumer
{
    private ObjectProvider<Pair> pairProvider;

    @Autowired
    public MyConsumer(ObjectProvider<Pair> pairProvider)
    {
        this.pairProvider = pairProvider;
    }

    public void doSomethingWithPairs()
    {
        Pair pairOne = pairProvider.getObject("a", "b");
        Pair pairTwo = pairProvider.getObject("z", "x");
    }
}

注意:您实际上并没有实现 ObjectProvider<> 接口; Spring 会自动为您完成。您只需要定义 bean 工厂方法。

原文由 HairOfTheDog 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题