Reputation: 3132
I am trying to inject an object into a singleton class implementation. Something like this
public class MyObjectWrapper implements ApplicationContextAware {
public static MyObject myObject;
private ApplicationContext ctxt;
private MyObjectWrapper() {}
public static synchronized MyObject getImpl() {
if (myObject!=null)
return myObject;
MyObjectWrapper myObjectWrapper=new MyObjectWrapper();
this.myObject = (MyObject) myObjectWrapper.getCtxt().getBean("myobject");
return myObject;
}
@Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
logger.debug("setApplicationContext - " + arg0);
this.ctxt = arg0;
}
public ApplicationContext getCtxt() {
return ctxt;
}
public void setCtxt(ApplicationContext ctxt) {
this.ctxt = ctxt;
}
}
It doesnt work, that is when i call MyObjectWrapper.getImpl() i get a null MyObject. i have bean entries for myobject and MyObjectWrapper.
I know using getBean is not the best practice but in this particular example is it acceptable? What is the downside? If not here, i will being doing a similar getBean call in my Main method.
I can do a getBean in my main method (i am accessing the application context there), however i just wanted this Wrapper class to be responsible for creation of this singleton. Objects that need MyObject can just call MyObjectWrapper.getImpl() and they get a singleton object.
Any feedback on the same would be appreciated.
Upvotes: 2
Views: 6565
Reputation: 42849
This won't work because you are instantiating a new instance of MyWrapperObject
in your static getInstance()
method. Because you are instantiating it, the bean is NOT Spring managed, and therefore the ApplicationContextAware
method, setApplicationContext(...)
, will not be called by Spring.
I am not a fan of this code, but if you want to do something like this, I do have a suggestion. Instead of saving the ApplicationContext
to an instance member, save it to a static member. Then, in your static getInstance()
method, do not create a new instance of MyWrapperObject
, just use the static ApplicationContext
that you have to create the instance of MyObject
. If this class is indeed a Spring singleton, then you should have nothing to worry about.
Something like this:
public class MyObjectWrapper implements ApplicationContextAware {
private static MyObject myObject;
private static ApplicationContext ctxt;
private MyObjectWrapper() {}
public static synchronized MyObject getImpl() {
if (myObject!=null)
return myObject;
this.myObject = ctxt.getBean("myobject", MyObject.class);
return myObject;
}
@Override
public void setApplicationContext(ApplicationContext arg0) throws BeansException {
ctxt = arg0;
}
}
Also, don't make your object public
. It is a singleton for a reason. You want everyone that calls getInstance()
to get the same instance of the object. If you make it public
, then anyone can get a hold of it and reassign it if they want. It somewhat defeats the purpose...
Upvotes: 5