Imagine you are working on a Spring application where most of the objects are created using Spring annotations and fields are also injected using Spring mechanisms (using @Autowired or XML configuration).
Now you develop a component or use an API which is written without any use of Spring and you need one of your Spring managed classes in it.
Suppose below is the class which performs various operations and is managed by Spring
/* * Spring managed class which handles utility tasks * such as database, file etc. */ @Component public class MainSpringClass { @Autowired DaoClass savesInDatabase; @Autowired FileManager fileBasedOperations; // other utility fields and methods }
Now you modify a set of classes from an open source library which does not use Spring or write your own class to perform some operation and one of these classes needs to use the above Spring managed class.
Example, see below class
public class ApiClass { MainSpringClass springObject; public void performDatabaseOperation() { // require an instance of MainSpringClass (Spring Managed class) } }
Since the above class is from an API, its object can only be created using new
operator.
Or let’s say this is your own class but you cannot create its object using Spring and you need to create its object using new
operator.
Now you are stuck !!!!
because the moment you create its object using new
, you will not be able to get the instance of Spring managed class.
So the question lies, how will you get instance of MainSpringClass
in ApiClass
. Or,
How to get the instance of Spring Managed class into a Non-Spring Managed class ?
There is one way out.
If somehow we can get access to Spring’s application context in any non-Spring class, instance of any Spring class can be retrieved.
Getting Spring Application Context in a class
There are many ways to get an instance of Spring application context in a class.
One of them is to make the class implement org.springframework.context.ApplicationContextAware
interface.
Any class which implements org.springframework.context.ApplicationContextAware
interface has to implement its setApplicationContext()
method.
This is a callback method which accepts an argument of type org.springframework.context.ApplicationContext
.
It is automatically called by Spring during startup and Spring passes its application context into this method.
Thus if we create a class which has access to Spring’s application context and add a public static
method to this class which returns this application context, then it would be easy to get application context anywhere in the application.
Once we get Application context in a class, we can get reference to any bean registered in this context.
import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContext implements ApplicationContextAware { @Autowired static ApplicationContext context; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { context = applicationContext; } public static ApplicationContext getAppContext() { return context; } }
Since the above class is annotated with @Component
annotation, it is automatically called by Spring during startup and as this class implements ApplicationContextAware
interface, it has to implement setApplicationContext
method which is supplied with Application context by Spring as explained above.
Thus, our new class(non Spring class) which required a Spring managed bean now becomes :
public class ApiClass { public void performDatabaseOperation() { //get application context ApplicationContext context = SpringContext.getApplicationContext(); // get instance of MainSpringClass (Spring Managed class) MainSpringClass springObject = (MainSpringClass)context.getBean("mainSpringClass"); // use this spring object to call its methods } }
Let’s tweak in:
- Application context’s
getBean()
method returnsjava.lang.Object
. It has to be casted to the appropriate type before using. - A bean is registered with its class name in lower case. In the above example,
MainSpringClass
was registered as “mainSpringClass”. - Method to get Application Context in
SpringContext
class above was declared aspublic static
so that itsgetApplicationContext()
method can be accessed directly by class name and you are not required to create its object.
Refer static keyword.
Thanks!
Great
Wonderful