We already know how to get an object from the Spring container using the getBean() method but sometimes we have the opposite need. That is, we want to use the Spring container in our object to have access to other objects in its container. Is there a way to do that?
I can say, Spring supports us to do that. By implementing the ApplicationContextAware interface, our object can use the Spring container.
Let’s take an example to see how it works.
In this example, we have an application that manages classes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
package com.huongdanjava.springaware; public class Clazz { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } |
Here, I will declare two classes in the Spring container. The bean id of each class is the name of the class. As below:
1 2 3 4 5 6 7 8 9 10 11 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="clazzA" class="com.huongdanjava.springaware.Clazz"> </bean> <bean id="clazzB" class="com.huongdanjava.springaware.Clazz"> </bean> </beans> |
Now, I have the need from Class A, I need to know the name of class B in the Spring container. To do this, you need to access the Spring container from class A first. Just add the implementation of the ApplicationContextAware interface as shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package com.huongdanjava.springaware; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class Clazz implements ApplicationContextAware { private String name; private ApplicationContext context; public String getName() { return name; } public void setName(String name) { this.name = name; } public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context; } public ApplicationContext getContext() { return context; } } |
OK, now from class A we can get the object of class B:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.huongdanjava.springaware; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Clazz clazzA = (Clazz) context.getBean("clazzA"); Object clazzB = clazzA.getContext().getBean("clazzB"); } } |
Here, perhaps, some of you will wonder why just implementing the ApplicationContextAware interface, the class object A can call the Spring container. Let me answer that: Spring uses the following code to automatically put the Spring container into the object needed.
1 2 3 4 5 |
Class<?> beanClass = beanDefinition.getClass(); Object bean = beanClass.newInstance(); if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(ctx); } |
As you can see, any object that is an instance of the ApplicationContextAware interface, during the runtime, that object will be automatically assigned the Spring container, here is the ApplicationContext.
Now back to our needs to take the name of class B.
To be able to use the bean id as the name of the class object B, we need to implement the BeanNameAware interface for this object. The code will look like the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
package com.huongdanjava.springaware; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; public class Clazz implements ApplicationContextAware, BeanNameAware { private String name; private ApplicationContext context; public String getName() { return name; } public void setName(String name) { this.name = name; } public void setApplicationContext(ApplicationContext context) throws BeansException { this.context = context; } public ApplicationContext getContext() { return context; } public void setBeanName(String name) { this.name = name; } } |
Then, to get the name of class B, we just do the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.huongdanjava.springaware; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Clazz clazzA = (Clazz) context.getBean("clazzA"); Clazz clazzB = (Clazz) clazzA.getContext().getBean("clazzB"); System.out.println("\n" + clazzB.getName()); } } |
Result: