简体   繁体   中英

Prototype scope not working

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

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.

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() .

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();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM