Search code examples
javaspringspring-java-config

Get New Instance Of Prototype Scoped Spring Component Using JavaConfig


I want to have a Spring component with prototype scope instantiated as needed at runtime, using pure Java implementation (Spring JavaConfig annotations). Say i have a bean as follows:

@Component
@Scope("prototype")   
public class MyTask {

    @Autowired
    Field myField;

    runTask() {...}
}

I want to be able to do the following:

MyTask task = //instantiate new task
task.runTask();

I can always use:

ApplicationContext.getBean(MyTask.class)

But that would completely contradict the notion of inversion of control. Can this be done with JavaConfig pure Java implementation (i.e. no use of xml files)?

UPDATE:

To be more specific, I'm looking for a way that will be similar to the xml based solution of lookup-method factory that is explained in this SO post


Solution

  • Scope 'prototype' means that each time you call beanFactory.getBean(), you get a fresh instance. And when you inject a dependency (for instance, via @Autowired), Spring (internally) calls that getBean() only once per injection point.

    To call it multiple times, you need a BeanFactory, or just call that @Bean-annotated method in your configuration.

    An interesting use case of prototype scope with @Configuration is described here: Spring Java Config: how do you create a prototype-scoped @Bean with runtime arguments?

    Update

    You could implement what you described without the prototype scope.

    @Component
    public class MyTaskFactoryImpl implements MyTaskFactory {
        @Autowired
        Field myField;
    
        @Override
        public MyTask newTask() {
            return new MyTask(myField);
        }
    }
    

    And in MyTask:

    public class MyTask {
    
        final Field myField;
    
        public MyTask(Field myField) {
            this.myField = myField;
        }
    
        public void runTask() {...}
    }
    

    Then inject MyTaskFactory taskFactory and use it:

    MyTask task = taskFactory.newTask();
    task.runTask()