tags:

views:

34

answers:

3

Hi,

I've created a prototype scoped bean in my application and I'm injecting that to another bean using a setter. But when I'm using the injected bean in my class it is always using the same instance instead of new instance every time.

Here is a snapshot of the code

<bean name="prototypeScope" Class="A" scope="prototype">
</bean>

<bean Class="Consumer">
    <property name="a" ref="prototypeScope" />
</bean>

public class Consumer{
    privare A a;

    public void setA(A a){
        this.a = a;
    }


    public void consume(){

        a.doSomething();

    }
}

Regards

+4  A: 

It is an common mistake related to prototype scoped beans.

A new instance of the prototype scoped bean will be created only when we request a copy of the bean from the application context, not every time we call a method on the instance.

In your case you are injecting the prototype scoped bean to another bean using the setter of the later, so then the second class is created a new instance of the prototype scoped bean will be created. But it will use the same instance as long as it is replace by another instace mannualy by you.

If you want a new instance of the prototype scoped bean during a particular operation like a method call, you have to get a new instance of the bean from the application content.

Ex:

<bean name="prototypeScope" Class="A" scope="prototype">
</bean>

<bean Class="Consumer">
</bean>

Java code:

public class Consumer implements ApplicationContextAware{
    privare ApplicationContext context;

    public void setApplicationContext(ApplicationContext context){
        this.context = context;
    }


    public void consume(){

        A a = context.getBean("prototypeScope", A.class);

        a.doSomething();

    }
}

In this example when ever the consume method is called a new instance of class A is created.

Ram
I split the source code in two parts. If you use two different languages in the same listing, the syntax highlighting doesn't work properly.
seanizer
+2  A: 

There are two main ways to deal with the Singleton-Bean-has-Prototype-dependency problem.

One is tight coupling to the applicationContext, as in Ram's answer, the other is Lookup Method Injection.

Basically, you make your bean class abstract and add an abstract method for the dependency, something like this:

public abstract class MyBean{

    public abstract MyService lookupService();

}

Then you add a bean definition something like this:

<bean id="myBean" class="fiona.apple.sucks.MyBean">
<!-- sorry, just wanted to insert sucks after Spring's fiona apple example,
didn't think about the connotations :-) -->
    <lookup-method name="lookupService"/>
</bean>

Now Spring will create a CGLib subclass of your bean class that will return a new Prototype instance for every time you call myBean.lookupService().

seanizer
A: 

I used such approach once..

First I declared a bean

<bean id="notSingelton" class="com.Foo" singleton="false" />

Then made an interface

public interface FooFactory {
    Foo make(String name);
}

wrapped it into ServiceLocatorFactoryBean

<bean id="fooFactory"
     class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
    <property name="serviceLocatorInterface" value="com.FooFactory" />
</bean>

<bean id="consumer" class="com.Consumer">
    <constructor-arg ref="fooFactory" />
</bean>

And consumer class looked something like that:

public class Consumer {
    private FooFactory fooFactory;

    public Consumer(FooFactory fooFactory) {
         this.fooFactory = fooFactory;
    }


    public void consume(){
        Foo foo = fooFactory.make("notSingelton");
        foo.doSomething();
    }
}
vrm