Spring bean with runtime constructor arguments

拈花ヽ惹草 提交于 2019-12-17 18:03:57

问题


I want to create a Spring bean in Spring Java configuration with some constructor arguments passed at runtime. I have created the following Java config, in which there is a bean fixedLengthReport that expects some arguments in constructor.

@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);
    }
}

But i am getting error that sourceSystem couldn't wire because no bean found. How can I create bean with runtime constructor arguments?

I am using Spring 4.2


回答1:


You can use a prototype bean along with a 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") means that Spring will not instantiate the bean right on start, but will do it later on demand. Now, to customize an instance of the prototype bean, you have to do the following.

@Controller
public class ExampleController{

   @Autowired
   private BeanFactory beanFactory;

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

Note, because your bean cannot be instantiated on start, you must not Autowire your bean directly; otherwise Spring will try to instantiate the bean itself. This usage will cause an error.

@Controller
public class ExampleController{

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

}



回答2:


You code looks fine, to get the prototype with parameters use the BeanFactory#getBean(String name, Object... args) method.

Look at Spring Java Config: how do you create a prototype-scoped @Bean with runtime arguments? BeanFactory#getBean(String name, Object... args) would be what you are looking for.

I guess that your IDEA (in my case IntelliJ IDEA version 15.) give you the error and it’s not a runtime/compile time error.

In IntelliJ you can change the setting of Spring inspections.

  • Go to file -> settings.
  • Type inspections in the search box.
  • Go to Spring Core->Code->Autowire for Bean Classes.
  • Change from "Error" to “weak warning”



回答3:


This can be achieved with Spring's ObjectProvider<> class which was introduced in Spring 4.3. See Spring's documentation for additional details.

The gist is to define the bean factory method for the object to be provided, inject the ObjectProvider<> in your consumer and create new instances of the object to be provided.

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");
    }
}

NOTE: you don't actually implement the ObjectProvider<> interface; Spring does that for you automagically. You just need to define the bean factory method.



来源:https://stackoverflow.com/questions/35108778/spring-bean-with-runtime-constructor-arguments

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!