I may be wrong here , but i am unable to figure out why is Spring creating 2 different objects from a Singleton class. Following is the code:
public class DbSingleTOn {
private static DbSingleTOn dbSingleTOn = new DbSingleTOn();
private DbSingleTOn() {
}
public static DbSingleTOn getInstance() {
return dbSingleTOn;
}
}
public class MyApp {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext(
"spring-singleton.xml");
DbSingleTOn dbSingleTOn = context.getBean(DbSingleTOn.class);
System.out.println(dbSingleTOn.hashCode());
DbSingleTOn dbSingleTOn1 = context.getBean(DbSingleTOn.class);
System.out.println(dbSingleTOn1.hashCode());
context.registerShutdownHook();
}
}
Output:
18885489
17045421
Spring Config XML:
<bean id="bean1" class="com.singleton.DbSingleTOn" scope="prototype" >
</bean>
It is expected to get different object for a normal class using "prototype" scope, however, Why would "prototype" create 2 objects from Singleton class ?
Just because you create a singleton in a static field this does not have an impact on spring. Spring is simply not aware of that.
Prototype scope just means: return a new instance when getBean is called.
Singleton scope means: create an instance once and always return this one.
Two things. One, Spring has no idea (and really doesn't care) how your class is setup. The fact that you've implemented a programming pattern means nothing to Spring. Two, Spring uses reflection to instantiate the bean types you declare and therefore can use your private constructors.
Every time you request a prototype scoped bean from Spring, it will create a new instance of the bean.
If you don't setup directly how to instantiate the bean, Spring use reflection to call a constructor for create beans. In addition use of default singleton scope, you can also setup factory-method in your xml config to getInstance to tell Spring how to create your beans.
Related
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?
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 {
// ...
}
Singleton bean is created only once so the prototype bean which is injected also will be created once at the instantiation of singleton bean.The same instance of prototype bean will be used for every request.
If new instance of prototype bean will be created for each request at runtime ,the below method Injection can be used
Example
public class Singleton {
private Prototype prototype;
public Singleton(Prototype prototype) {
this.prototype = prototype;
}
public void doSomething() {
prototype.foo();
}
public void doSomethingElse() {
prototype.bar();
}
}
public abstract class Singleton {
protected abstract Prototype createPrototype();
public void doSomething() {
createPrototype().foo();
}
public void doSomethingElse() {
createPrototype().bar();
}
}
<bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
<bean id="singleton" class="sample.MySingleton">
<lookup-method name="createPrototype" bean="prototype" />
</bean>
Right way to achieve it - use lookup method injection and everywhere where you used beans use lookup method invocation (detailed answer)
Since Spring 4.1 you can use annotation #Lookup
#Lookup
public PrototypeBean getPrototypeBean() {
return null;
}
Every time you will call method getPrototypeBean() - you will receive new prototype bean instance.
Don't worry about empty method realization: Spring will override it for you.
Read more in official documentation.
Spring wires up your beans in a pretty straight forward way. I'm working in a large commercial application, and I inserted the following code snippets to verify the load order.
1) All of your singleton bean class structures are initially loaded by Spring (as long as Spring is aware of them via annotations and/or xml). This only ever happens once. You can test this by logging or printing in a static block:
static {
log.info("#### classNameHere loaded"); //or println if no log setup
}
2) Spring creates all singleton instances that it is aware of (but not prototypes! Prototype instances WILL be created IF they are referenced inside a singleton bean - there class structures are of course loaded first). You can test this by adding this method to each class:
#PostConstruct
public void methodHitAfterClassInstantiation() {
LOGGER.info("#### instance of classNameHere");
}
So in your example, the class structures of SingletonBean is loaded when Spring starts up. A new instance of SingletonBean is created.
And because PrototypeBean is Autowired inside of SingletonBean, its class structure is loaded and an instance of it is created. Now, if there was another bean, say AnotherSingletonBean, with an Autowired PrototypeBean inside
of it, then a DIFFERENT instance of PrototypeBean would be created (no need to load the class structure again). So there is only ever 1 SingletonBean, and inside of it is a PrototypeBean, which
will always point to the same bean. Because of this, singletons should always be stateless, as all of your other beans that use a singleton will be pointing at the
same object. But you CAN maintain state in a prototype bean, because wherever you create a new reference, you will be pointing at another bean object.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype
I'm working with some existing code and it is doing things I haven't seen before. I've dealt with autowiring prototype beans into singletons using method injection or getting the bean from the context using getBean(). What I am seeing in this code I am working on is a bean that is a prototype and retrieved using getBean(), and it has autowired dependencies. Most of these are singleton beans, which makes sense. But there is an autowire of another prototype bean, and from what I see, it does seem like it is getting a new bean. My question is when you autowire a prototype into a prototype, will that give you a new instance? Since the autowire request is not at startup but rather when this bean is created, does it go and create a new instance? This goes against what I thought about autowire and prototype beans and I wanted to hear an answer from out in the wild. Thanks for any insight. I'm trying to minimize my refactoring of this code as it is a bit spaghetti-ish.
example:
#Scope("prototype")
public class MyPrototypeClass {
#Autowired
private ReallyGoodSingletonService svc;
#Autowired
private APrototypeBean bean;
public void doSomething() {
bean.doAThing();
}
}
#Scope("prototype)
public class APrototypeBean {
private int stuffgoeshere;
public void doAThing() {
}
}
So when doSomething() in MyPrototypeClass is called, is that "bean" a singleton or a new one for each instance of MyPrototypeClass?
In your example, the APrototypeBean bean will be set to a brand new bean which will live through until the instance of MyPrototypeClass that you created is destroyed.
If you create a second instance of MyPrototypeClass then that second instance will receive its own APrototypeBean. With your current configuration, every time you call doSomething(), the method will be invoked on an instance of APrototypeBean that is unique for that MyPrototypeClass object.
Your understanding of #Autowired or autowiring in general is flawed. Autowiring occurs when an instance of the bean is created and not at startup.
If you would have a singleton bean that is lazy and that bean isn't directly used nothing would happen as soon as you would retrieve the bean using for instance getBean on the application context an instance would be created, dependencies get wired, BeanPostProcessors get applied etc.
This is the same for each and every type of bean it will be processed as soon as it is created not before that.
Now to answer your question a prototype bean is a prototype bean so yes you will receive fresh instances with each call to getBean.
Adding more explanation to #Mark Laren's answer.
As explained in Spring 4.1.6 docs
In most application scenarios, most beans in the container are
singletons. When a singleton bean needs to collaborate with another
singleton bean, or a non-singleton bean needs to collaborate with
another non-singleton bean, you typically handle the dependency by
defining one bean as a property of the other. A problem arises when
the bean lifecycles are different. Suppose singleton bean A needs to
use non-singleton (prototype) bean B, perhaps on each method
invocation on A. The container only creates the singleton bean A once,
and thus only gets one opportunity to set the properties. The
container cannot provide bean A with a new instance of bean B every
time one is needed.
Below approach will solve this problem, but this is not desirable because this code couples business code with Spring framework and violating IOC pattern. The following is an example of this approach:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class CommandManager implements ApplicationContextAware {
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// notice the Spring API dependency!
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
So, there are 2 desirable ways to solve this problem.
1. Using Spring's method injection
As name suggests, Spring will implement & inject our abstract method by using #Lookup annotation from Spring 4 or tag if you use xml version. Refer this DZone article.
By using #Lookup.
from Java Doc...
An annotation that indicates 'lookup' methods, to be overridden by the
container to redirect them back to the BeanFactory for a getBean call.
This is essentially an annotation-based version of the XML
lookup-method attribute, resulting in the same runtime arrangement.
Since:
4.1
#Component
public class MyClass1 {
doSomething() {
myClass2();
}
//I want this method to return MyClass2 prototype
#Lookup
public MyClass2 myClass2(){
return null; // No need to declare this method as "abstract" method as
//we were doing with earlier versions of Spring & <lookup-method> xml version.
//Spring will treat this method as abstract method and spring itself will provide implementation for this method dynamically.
}
}
The above example will create new myClass2 instance each time.
2. Using Provider from Java EE (Dependency Injection for Java (JSR 330)).
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
#Component
public static class SomeRequest {}
#Service
public static class SomeService {
#Autowired
javax.inject.Provider<SomeRequest> someRequestProvider;
SomeRequest doSomething() {
return someRequestProvider.get();
}
}
The above example will create new SomeRequest instance each time.
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?
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 {
// ...
}
Singleton bean is created only once so the prototype bean which is injected also will be created once at the instantiation of singleton bean.The same instance of prototype bean will be used for every request.
If new instance of prototype bean will be created for each request at runtime ,the below method Injection can be used
Example
public class Singleton {
private Prototype prototype;
public Singleton(Prototype prototype) {
this.prototype = prototype;
}
public void doSomething() {
prototype.foo();
}
public void doSomethingElse() {
prototype.bar();
}
}
public abstract class Singleton {
protected abstract Prototype createPrototype();
public void doSomething() {
createPrototype().foo();
}
public void doSomethingElse() {
createPrototype().bar();
}
}
<bean id="prototype" class="ch.frankel.blog.Prototype" scope="prototype" />
<bean id="singleton" class="sample.MySingleton">
<lookup-method name="createPrototype" bean="prototype" />
</bean>
Right way to achieve it - use lookup method injection and everywhere where you used beans use lookup method invocation (detailed answer)
Since Spring 4.1 you can use annotation #Lookup
#Lookup
public PrototypeBean getPrototypeBean() {
return null;
}
Every time you will call method getPrototypeBean() - you will receive new prototype bean instance.
Don't worry about empty method realization: Spring will override it for you.
Read more in official documentation.
Spring wires up your beans in a pretty straight forward way. I'm working in a large commercial application, and I inserted the following code snippets to verify the load order.
1) All of your singleton bean class structures are initially loaded by Spring (as long as Spring is aware of them via annotations and/or xml). This only ever happens once. You can test this by logging or printing in a static block:
static {
log.info("#### classNameHere loaded"); //or println if no log setup
}
2) Spring creates all singleton instances that it is aware of (but not prototypes! Prototype instances WILL be created IF they are referenced inside a singleton bean - there class structures are of course loaded first). You can test this by adding this method to each class:
#PostConstruct
public void methodHitAfterClassInstantiation() {
LOGGER.info("#### instance of classNameHere");
}
So in your example, the class structures of SingletonBean is loaded when Spring starts up. A new instance of SingletonBean is created.
And because PrototypeBean is Autowired inside of SingletonBean, its class structure is loaded and an instance of it is created. Now, if there was another bean, say AnotherSingletonBean, with an Autowired PrototypeBean inside
of it, then a DIFFERENT instance of PrototypeBean would be created (no need to load the class structure again). So there is only ever 1 SingletonBean, and inside of it is a PrototypeBean, which
will always point to the same bean. Because of this, singletons should always be stateless, as all of your other beans that use a singleton will be pointing at the
same object. But you CAN maintain state in a prototype bean, because wherever you create a new reference, you will be pointing at another bean object.
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype
I have a class that looks like so:
public class Configurator {
private static Configurator INSTANCE = null;
private int maxRange = 1;
// many other properties; each property has a default value
private static synchronized Configurator getInstance() {
if(INSTANCE == null)
return new Configurator();
return INSTANCE;
}
public static int getMaxRange() {
getInstance().maxRange;
}
public static void setMaxRange(int range) {
getInstance().maxRange = range;
}
// Getters and setters for all properties follow this pattern
}
It serves as a global configuration object that can be set on app startup, and then is used by dozens of classes throughout the project:
// Called at app startup to configure everything
public class AppRunner {
Configurator.setMaxRange(30);
}
// Example of Configurator being used by another class
public class WidgetFactory {
public void doSomething() {
if(Configurator.getMaxRange() < 50)
// do A
else
// do B
}
}
I'm now importing this code into a Spring project, and am trying to configure my Sprinig XML (beans). My guess is that I could define a lone Configurator bean like so (or something similar):
<bean id="configurator" class="com.me.myapp.Configurator" scope="singleton">
<property name="maxRange" value="30"/>
<!-- etc., for all properties -->
</bean>
That way, when WidgetFactory#doSomething executes, Spring will have already loaded the Configurator class and configured it ahead of time.
Is it correct for me to set the scope="singleton", or does this not matter? Am I setting the static properties correctly? Is there anything else I need to do or consider here? Thanks in advance.
There are some difference between Singleton as a design pattern and Spring's singleton facility. Singleton as a design pattern will ensure you have one object of class defined per Class Loader. Spring's singleton facility (and approach), in contrast, will define one instance per Spring Context.
In this case you can utilize your getInstance() method to be used by Spring to grab your object instance:
<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>
With Spring the singleton bean scope is the default therefore you don't need to define it.
If you want to use configurator as a Spring bean you will have to inject it in other objects, not use getInstance() to grab it. So in other Spring beans use #Autowired or define reference to bean through xml file. If you don't reorganize usage of configurator in other classes, there will no be difference, Spring will instantiate your class, but you will use it as before.
Also I saw that you have an error in designing your singleton. Your getInstance() method should be public, and other methods should not be static. In the example you've used you should use Singleton like this:
Configurator.getInstance().someMethod()
In this case you actually just use the Singleton class, without instantiating any objects! See wikipedia on Singleton (with Java example) for more information on the Singleton design pattern and how to use it.
NOTE: It's worth knowing and attempting to use Configurator as a Singleton and make use Spring's singleton facility. If you do this the benefits will be that you can
Remove the getInstance() method
Make your constructor public
Let the Spring instantiate that single object.
Beans are singleton by default. You can find this/more information out via the spring website.
You shouldn't instantiate a new Configurator in getInstance because it won't refer to the spring loaded bean and that could cause some serious issues. You can wire this bean in and then leave it alone, it won't be null because you've wired it in (and if it is your program will have failed initialising).
Yes, if you want something global, singleton scope is the right option.
a few things worth mentioning here are :
The default scope in spring is singleton, so you don't need to
explicitly set your bean as singleton scope.
Using Spring you do not need to write Singleton pattern style code, such as private instances and a factory methods. That is because Spring will
guarantee that there is only one single instance per Spring
container. Not even to say, your factory method is private.
By the way: this is not Thread-safe:
if(INSTANCE == null)
return new Configurator();
return INSTANCE;
}
Whereas this would be:
private static Configurator INSTANCE = new Configurator();
(Eager Initialization)
private static volatile Singleton _instance = null;
(Lazy initialization with volatile keyword)
It has to do with the way Java allocates Memory and creates instances. This is not atomic, but done in two steps and can be interfered by the thread scheduler.
See also http://regrecall.blogspot.de/2012/05/java-singleton-pattern-thread-safe.html.
I am converting a singleton to a Spring bean, so that if the singleton fails to initialize, then entire web application's spring context doesn't load properly.
The advantage of making the Spring context not load properly, is that people will take notice and fix the configuration during deployment itself. As opposed to using 'non-spring bean' singleton: when that throws exception during initialization, nobody notices.. until a actual user complains of missing functionality.
My changes are working as expected.. but I am not sure if I am doing the right thing.
Any thoughts?
The code looks like this:
public class MySingleton {
private static MySingleton INSTANCE = null;
private MySingleton(){}
public static MySingleton getInstance(){
if(INSTANCE == null){
synchronized(MySingleton.class){
if(INSTANCE == null){
try{
doWork()
}catch(Exception e){
throw new IllegalStateException("xyz", e);
}
INSTANCE = new MySingleton();
}
}
}
return INSTANCE;
}
private static void doWork() {
// do some work
}
}
And in the spring config xml, the bean will be defined as:
<bean id="MySingletonBean"
class="com.MySingleton"
factory-method="getInstance" lazy-init="false" singleton="true">
</bean>
Note:
Most of this is similar to the strategy discussed in this article:
http://springtips.blogspot.com/2007/06/configuration-hell-remedy-with.html
Edit 1:
The classes that use this singleton, are not spring beans themselves.. they are just non-spring pojos, that I can't convert to spring. They must rely on getInstance() method get hold of the Singleton.
Edit 2: (copying a comment I made below into this description section)
I am trying to target two things:
I want Spring to initialize the singleton. So that if the
initialization fails, then the application loading fails.
I want the other classes be able to use classes without having to rely on contextAwareObj.getBean("MySingleton")
EDIT 3 (FINAL):
I decided to make this class a singleton.. and am not making it a spring bean. If it fails to initialize, it will log something in the Log file.. hopefully the person doing deployment takes notice.... I abandoned the approach I mentioned earlier because I feel it will create a maintenance nightmare in future, so I had to pick between - singleton - or - spring bean. I chose singleton.
You must declare the INSTANCE field as volatile for double-checked locking to work correctly.
See Effective Java, Item 71.
Why are you using singleton pattern on the first place? Just let Spring create bean for you (with default singleton scope) and... use it. Of course always somebody might create the bean by hand, but this was never a problem in my case.
Dependency injection and Spring-managed bean lifecycle will ease your life significantly (just see how many pitfalls you can avoid). Also note that exceptions thrown from c-tor or #PostContruct method will propagate and cause application context startup to fail as well.
UPDATE: I get your point. This is what came in to my mind:
#Service
public class Singleton {
private static AtomicReference<Singleton> INSTANCE = new AtomicReference<Singleton>();
public Singleton() {
final Singleton previous = INSTANCE.getAndSet(this);
if(previous != null)
throw new IllegalStateException("Second singleton " + this + " created after " + previous);
}
public static Singleton getInstance() {
return INSTANCE.get();
}
}
And let Spring do its job. You can use DI when possible and Singleton.getInstance() where you have to.
Also there are more hard-core solutions like compile-time AspectJ weaving and injecting Spring beans basically to everything.
I'm not sure why you'd want to do this. When you tell Spring that a bean should be a singleton, the corresponding class does not need to be a singleton, and does not need a factory. Spring just simply only ever creates one instance.
The linked article makes no sense to me, since there is NO injection happening, that I can see: "AnyService" is calling the singleton factory method; that the singleton is referenced in the app context is irrelevant until it's referenced, and it seems no other bean references it.
True singleton are hard to get working.
Volatile double-checked locking also does not work property. Read about it on wiki http://en.wikipedia.org/wiki/Double-checked_locking
Your best bet is to simply do this
public class MySingleton {
private static MySingleton INSTANCE = new MySingleton();
That is if you do not have any constructor parameters in your real code.
According to me this is a belts-and-suspenders solution.
If you create a bean and declare it as a singleton in the configuration then there should be no need to protect the bean against being multiply created.
You are now basically protecting yourself from someone wrongly configuring the bean.
I personally would "solve" that by documentation in the spring configuration and Javadoc.
To run code at startup (and fail on error) use one of the many ways to register startup events, e.g. see http://www.baeldung.com/running-setup-logic-on-startup-in-spring
Example:
#Component
public class InitializingBeanExampleBean implements InitializingBean {
private static final Logger LOG = Logger.getLogger(InitializingBeanExampleBean.class);
#Autowired
private Environment environment;
#Override
public void afterPropertiesSet() throws Exception {
LOG.info(Arrays.asList(environment.getDefaultProfiles()));
}
}
#Component
public class SingletonDAOImpl {
}
#Component
public class SingletonDAO {
#Autowired private SingletonDAOImpl instance;
public SingletonDAOImpl getInstance(){
return this.instance
}
}
public class WhateverPlaceYouNeedIt{
#Awtowired private SingletonDAO singletonDao;
public void useSIngleton() {
SingletonDAOImpl INSTANCE = singletonDao.getInstance();
}
}
I tried in so many ways to do something like SingletonDao.instance.doSomething()
but just is not in the spring way and you will find so many hacks in order to do this but is incorrect in my opinion
here
You have your Singleton, which can be changed after in a Multiton
For sure is a single implementation
is respecting the INSTANCE pattern as "getInstance"
Is in-memory so each time is the same object as in singleton
is the same principle applied slightly different, very simple, all the time try to KIS implementation(Keep it simple)