I need to get the spring application context from a non bean object. In another thread in SO, the accepted answer suggests to use singleton to get the application context. Getting Spring Application Context
But using singleton makes my code more coupled and less testable, the usual problems discussed in many threads (e.g. What is so bad about Singletons )
The question, is there an elegant way to get the application context from a non bean object without using singleton?
If you need to access the Spring Application context from the above non spring class, then you should create a subclass of ApplicationContextAware. This subclass must override the setApplicationContext method and Spring passes the associated application context in this method.
To get a reference to the ApplicationContext in a Spring application, it can easily be achieved by implementing the ApplicationContextAware interface. Spring will automatically detect this interface and inject a reference to the ApplicationContext: view rawMyBeanImpl. java hosted by GitHub.
I can have my class implement BeanFactoryAware to get a reference to my beanfactory. Then I can do beanFactory. getBean("name"); to get access to a single bean.
You can have two contexts within an application. If you have two contexts each will have its own singleton.
There's always the bootstrapping problem. For web applications there's usually the outer servlet filter that handles the situation.
If not a web-app, there's no way around some kind of outer singleton or bootstrapper. But; using a singleton here should only affect the testability of that single bootstrapper class. There should really only be very few places in your code that need to reference the container in any explicit manner. So it does not really increase coupling significantly.
Or to rephrase, there should really only be very few non-bean objects that need to access the spring container. If this is not the case, then you're probably not using spring optimally. And most/all of those that need the container should probably just implement BeanFactoryAware or ApplicationContextAware
I think your problem is near about the same I had few days back. I think the following should work for you:
First create a class called AppContextManager
like below:
@Component
public class AppContextManager implements ApplicationContextAware{
private static ApplicationContext _appCtx;
@Override
public void setApplicationContext(ApplicationContext ctx){
_appCtx = ctx;
}
public static ApplicationContext getAppContext(){
return _appCtx;
}
}
Annotate the above class with @Component
or declare a bean for AppContextManager in your application context xml
.
Now in your non-singleton
non-spring
instance use the following code snippet to obtain any other
spring bean:
ApplicationContext ctx = ApplicationContextManager.getAppContext();
SomeSpringBean bean = ctx.getBean(SomeSpringBean.class);
And this would give you the bean instance anywhere in your code.
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