Search code examples
springinversion-of-control

How to Instantiate spring bean with in a method with runtime constructor arguments?


I need to instantiate a bean ( EmployeeSaver) with in a method with parameter coming in dynamically. I can't use constructor setter for these values are not populated at config time.

Sample code:

class MyEmployeeBean{
    public void   saveEmployeeDetail (Employee employee , EmployeeHistory hist   ){
        EmployeeDetail detail = hist.getDetail();
        EmployeeSaver eSave = new EmployeeSaver(employee, detail)
        saver.saveEmployee();
    }
}

class EmployeeSaver {

    private Employee empl;
    private EmployeeDetail detail;

    public EmployeeSaver(Employee emp, EmployeeDetail det){

        empl = emp;
        detail = det;
    }

    public void saveEmployee(){
        // code to same the guy...
    }

}

As MyEmployeeSaver class don't have default constructor so it's throwing runtime exception. I am unsable to use following config as employeeDetail is not know until I do hist.getDetail() !

<bean id="mySaverBean" class="come.saver.EmployeeSaver">
    <constructor-arg name="empl" ref="employee" />
    <constructor-arg name="hist" ref = "employeeHistory" />
</bean>  

How to instantiate employeeSaverBean with constructor arguments?


Solution

  • You can't do this directly with Spring configuration, but using ApplicationContext.getBean(String beanName,Object...args) like described in this question. MyEmployeeBean must implements ApplicationContextAware to access Spring's context

    class MyEmployeeBean implements ApplicationContextAware {
      ApplicationContext applicationContext;
    
      void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
      }
    
      public void   saveEmployeeDetail (Employee employee , EmployeeHistory hist   ){
            EmployeeDetail detail = hist.getDetail();
            EmployeeSaver eSave = (EmployeeSaver)this.applicationContextnew.getBean("mySaverBean", employee, detail);
            saver.saveEmployee();
        }
    }
    

    and in beans.xml

    <bean id="mySaverBean" class="come.saver.EmployeeSaver" scope="prototype" />
    

    Remeber to addo scope="prototype" to let Spring create a new instance at every request.