Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the instance factory method to create prototype beans dynamically

I have a situation where I would like to dynamically create an object through a factory object, but the object needs to be created through the spring context, to allow autowiring of dependencies. I know that there are lots of other ways that I can solve this problem - using a service locator pattern for example - but I'd like to do it this way if possible.

Imagine I have two objects:

class OuterObject {
    List<InnerObjectInterface> innerObjs;
    ...
}
class InnerObject implements InnerObjectInterface{
    @Autowired
    SomeDependency someDependency;
    ...
}

I want to create a factory that does something along the lines of:

class OuterObjectFactory {
    private innerObject = new InnerObject();

    public OuterObject construct(params){
         OuterObject o = new OuterObject();
         List<InnerObjectInterface> inners = new ArrayList<InnerObjectInterface>();
         ...
         for(some dynamic condition){
             ...
             inners.add(createInnerObject());
             ...
         }
    }
    public createInnerObject(){
         return innerObject;
    }
}

My spring-context.xml would looks something like:

<bean id="outerObjectFactory" class="path.OuterObjectFactory" />
<bean id="innerObject" class="path.InnerObject" factory-bean="outerObjectFactory" factory-method="createInnerObject" />

This however, doesn't work. Only one innerObject is ever created, where I want it to act like it has scope="prototype". If I add scope="prototype" to the bean definition:

<bean id="innerObject" class="path.InnerObject" factory-bean="outerObjectFactory" factory-method="createInnerObject" scope="prototype"/>

Then it seems to create many innerObjects, but they aren't correctly wired. My co-worker believes that the documentation found here implies that the factory bean is only used to initialize a bean, but I don't find that obvious.

I'd appreciate it if anyone could clear up my understanding here, and possibly even suggest a better way of modelling the factory pattern with wiring than what I am doing.

Thanks!

like image 896
idbentley Avatar asked Apr 13 '11 21:04

idbentley


People also ask

How do you create a prototype bean?

Prototype Scope:If the scope is declared prototype, then spring IOC container will create a new instance of that bean every time a request is made for that specific bean. A request can be made to the bean instance either programmatically using getBean() method or by XML for Dependency Injection of secondary type.

What is factory bean and factory-method?

factory-method: represents the factory method that will be invoked to inject the bean. factory-bean: represents the reference of the bean by which factory method will be invoked. It is used if factory method is non-static.

Can we create prototype bean in singleton bean?

You cannot dependency-inject a prototype-scoped bean into your singleton bean, because that injection occurs only once, when the Spring container is instantiating the singleton bean and resolving and injecting its dependencies.


1 Answers

I think what you're saying is that you have a factory which is a singleton and you want it to create new objects of which you want a new one each time with full dependency injection. The old way of doing that was Method Injection which you link to above. The new (and arguably cleaner way) is to use a Scoped Proxy. You can either use annotations or regular config but the idea is that you create a proxy around the bean (e.g. the InnerObject). When ever you need a reference to it, spring will automatically provide you with a new copy with the appropriate dependencies inserted.

like image 55
dough Avatar answered Sep 22 '22 20:09

dough