1. Overview
The Spring Framework core is, simply put, an IoC container used to manage beans.
There are two basic types of containers in Spring – the Bean Factory and the Application Context. The former provides basic functionalities, which are introduced here; the latter is a superset of the former and is most widely used.
ApplicationContext is an interface in the org.springframework.context package and it has several implementations, and the ClassPathXmlApplicationContext is one of these.
In this article, we’ll focus on the useful functionalities provided by the ClassPathXmlApplicationContext.
2. Basic Usage
2.1. Initialize Container and Manage Beans
ClassPathXmlApplicationContext can load an XML configuration from a classpath and manage its beans:
We have a Student class:
public class Student { private int no; private String name; // standard constructors, getters and setters }
We configure a Student bean in classpathxmlapplicationcontext-example.xml and add it into a classpath:
<beans ...> <bean id="student" class="com.baeldung.applicationcontext.Student"> <property name="no" value="15"/> <property name="name" value="Tom"/> </bean> </beans>
Now we can use the ClassPathXmlApplicationContext to load the XML configuration and get the Student bean:
@Test public void testBasicUsage() { ApplicationContext context = new ClassPathXmlApplicationContext( "classpathxmlapplicationcontext-example.xml"); Student student = (Student) context.getBean("student"); assertThat(student.getNo(), equalTo(15)); assertThat(student.getName(), equalTo("Tom")); Student sameStudent = context.getBean("student", Student.class); assertThat(sameStudent.getNo(), equalTo(15)); assertThat(sameStudent.getName(), equalTo("Tom")); }
2.2. Multiple XML Configurations
Sometimes we want to use several XML configurations to initialize a Spring container. In that case, we simply need to add several configuration locations when constructing the ApplicationContext:
ApplicationContext context = new ClassPathXmlApplicationContext("ctx.xml", "ctx2.xml");
3. Additional Capabilities
3.1. Shut Down the Spring IoC Container Gracefully
When we use Spring IoC container in a web application, Spring’s web-based ApplicationContext implementations will shut down the container gracefully when the application is shut down, but if we use it in a non-web environment, such as a standalone desktop application, we have to register a shutdown hook with the JVM by ourselves to make sure the Spring IoC container is shut down gracefully and calls the destroy methods to release resources.
Let’s add a destroy() method to the Student class:
public void destroy() { System.out.println("Student(no: " + no + ") is destroyed"); }
We can now configure this method as the student bean’s destroy method:
<beans ...> <bean id="student" class="com.baeldung.applicationcontext.Student" destroy-method="destroy"> <property name="no" value="15"/> <property name="name" value="Tom"/> </bean> </beans>
We’ll now register a shutdown hook:
@Test public void testRegisterShutdownHook() { ConfigurableApplicationContext context = new ClassPathXmlApplicationContext( "classpathxmlapplicationcontext-example.xml"); context.registerShutdownHook(); }
When we run the test method, we can see the destroy() method is called.
3.2. Internationalization with MessageSource
The ApplicationContext interface extends the MessageSource interface, therefore provides internationalization functionality.
An ApplicationContext container automatically searches for a MessageSource bean in its initialization, and the bean must be named as messageSource.
Here is an example of using different languages with MessageSource:
First, let’s add a dialog directory into a classpath and add two files into the dialog directory: dialog_en.properties and dialog_zh_CN.properties.
dialog_en.properties:
hello=hello you=you thanks=thank {0}
dialog_zh_CN.properties:
hello=\u4f60\u597d you=\u4f60 thanks=\u8c22\u8c22{0}
Configure the messageSource bean in classpathxmlapplicationcontext-internationalization.xml:
<beans ...> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>dialog/dialog</value> </list> </property> </bean> </beans>
Then, let’s get different languages’ dialog words with MessageSource:
@Test public void testInternationalization() { MessageSource resources = new ClassPathXmlApplicationContext( "classpathxmlapplicationcontext-internationalization.xml"); String enHello = resources.getMessage( "hello", null, "Default", Locale.ENGLISH); String enYou = resources.getMessage( "you", null, Locale.ENGLISH); String enThanks = resources.getMessage( "thanks", new Object[] { enYou }, Locale.ENGLISH); assertThat(enHello, equalTo("hello")); assertThat(enThanks, equalTo("thank you")); String chHello = resources.getMessage( "hello", null, "Default", Locale.SIMPLIFIED_CHINESE); String chYou = resources.getMessage( "you", null, Locale.SIMPLIFIED_CHINESE); String chThanks = resources.getMessage( "thanks", new Object[] { chYou }, Locale.SIMPLIFIED_CHINESE); assertThat(chHello, equalTo("你好")); assertThat(chThanks, equalTo("谢谢你")); }
4. A Reference to the ApplicationContext
Sometimes we need to obtain the reference of ApplicationContext inside the beans managed by it, we can use ApplicationContextAware or @Autowired to do this. Let’s see how using ApplicationContextAware works:
We have a Course class with a name:
public class Course { private String name; // standard constructors, getters and setters }
We have a Teacher class which assembles its courses according to the container’s beans:
public class Teacher implements ApplicationContextAware { private ApplicationContext context; private List<Course> courses = new ArrayList<>(); @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } @PostConstruct public void addCourse() { if (context.containsBean("math")) { Course math = context.getBean("math", Course.class); courses.add(math); } if (context.containsBean("physics")) { Course physics = context.getBean("physics", Course.class); courses.add(physics); } } // standard constructors, getters and setters }
Let’s configure the course bean and the teacher bean in classpathxmlapplicationcontext-example.xml:
<beans ...> <bean id="math" class="com.baeldung.applicationcontext.Course"> <property name="name" value="math"/> </bean> <bean name="teacher" class="com.baeldung.applicationcontext.Teacher"/> </beans>
Then – test the injection of the courses property:
@Test public void testApplicationContextAware() { ApplicationContext context = new ClassPathXmlApplicationContext( "classpathxmlapplicationcontext-example.xml"); Teacher teacher = context.getBean("teacher", Teacher.class); List<Course> courses = teacher.getCourses(); assertThat(courses.size(), equalTo(1)); assertThat(courses.get(0).getName(), equalTo("math")); }
Besides implementing the ApplicationContextAware interface, using the @Autowired annotation has the same effect.
Let’s change the Teacher class to this:
public class Teacher { @Autowired private ApplicationContext context; private List<Course> courses = new ArrayList<>(); @PostConstruct public void addCourse() { if (context.containsBean("math")) { Course math = context.getBean("math", Course.class); courses.add(math); } if (context.containsBean("physics")) { Course physics = context.getBean("physics", Course.class); courses.add(physics); } } // standard constructors, getters and setters }
Then run that test, we can see the result is the same.
5. Conclusion
ApplicationContext is a Spring container with more enterprise-specific functionalities in comparison with BeanFactory, and the ClassPathXmlApplicationContext is one of its most commonly used implementation.
So in this article, we introduced several aspects of the ClassPathXmlApplicationContext, including its basic usage, its shutdown registration functionality, its internationalization functionality and obtaining of its reference.
As always, the complete source code for the example is available over on GitHub.