I am trying to inject a prototype
bean in a singleton
bean such that every new call to a singleton bean method has a new instance of the prototype bean.
Consider a singleton bean as below:
@Component public class SingletonBean { @Autowired private PrototypeBean prototypeBean; public void doSomething() { prototypeBean.setX(1); prototypeBean.display(); } }
I expect that every time the doSomething()
method is called, a new PrototypeBean
instance is utilized.
Below is the prototype bean:
@Component @Scope(value="prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) public class PrototypeBean { Integer x; void setX(Integer x) { this.x = x; } void display() { System.out.println(x); } }
What seems to be happening is that spring is being overeager in handing over a new instance of PrototypeBean in the doSomething()
method. That is, the 2 lines of code in the doSomething()
method are creating a new instance of prototypeBean in each line.
And so in the 2nd line - prototypeBean.display()
prints NULL.
What is missing in configuration for this injection?
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.
Let us look at a simple example when a prototype bean injected inside a singleton bean. Individually when a prototype bean used, every time a new instance is expected and for singleton the same instance. Singleton Bean always returns the same bean instance no matter where ever it is being referred.
As singleton beans are injected only once per their lifetime you need to provide scoped beans as proxies which takes care of that. @RequestScope is a meta-annotation on @Scope that 1) sets the scope to "request" and 2) sets the proxyMode to ScopedProxyMode.
From Spring documentation:
You do not need to use the
<aop:scoped-proxy/>
in conjunction with beans that are scoped as singletons or prototypes. If you try to create a scoped proxy for a singleton bean, the BeanCreationException is raised.
It seems the documentation has changed a bit for version 3.2 documentation where you can find this sentence:
You do not need to use the
<aop:scoped-proxy/>
in conjunction with beans that are scoped as singletons or prototypes.
It seems that its not expected you use a proxied prototype bean, as each time it is requested to the BeanFactory
it will create a new instance of it.
In order to have a kind of factory for your prototype bean you could use an ObjectFactory
as follows:
@Component public class SingletonBean { @Autowired private ObjectFactory<PrototypeBean> prototypeFactory; public void doSomething() { PrototypeBean prototypeBean = prototypeFactory.getObject(); prototypeBean.setX(1); prototypeBean.display(); } }
and your prototype bean would be declared as follows:
@Component @Scope(value="prototype") public class PrototypeBean { // ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With