Spring bean with runtime constructor arguments

suraj bahl picture suraj bahl · Jan 31, 2016 · Viewed 51.5k times · Source

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

Answer

Ken Bekov picture Ken Bekov · Jan 31, 2016

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;

}