具有运行时构造函数参数的 Spring Bean

2022-09-01 02:26:23

我想在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?

我正在使用春季 4.2


答案 1

您可以将原型 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;

}

答案 2

这可以通过Spring的课程来实现,该课程是在Spring 4.3中引入的。有关其他详细信息,请参阅Spring的文档ObjectProvider<>

要点是为要提供的对象定义 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");
    }
}

注意:您实际上并没有实现该接口;春天会自动为你做这件事。您只需要定义Bean Factory方法。ObjectProvider<>


推荐