Partner – Microsoft – NPI (cat= Spring)
announcement - icon

Azure Spring Apps is a fully managed service from Microsoft (built in collaboration with VMware), focused on building and deploying Spring Boot applications on Azure Cloud without worrying about Kubernetes.

And, the Enterprise plan comes with some interesting features, such as commercial Spring runtime support, a 99.95% SLA and some deep discounts (up to 47%) when you are ready for production.

>> Learn more and deploy your first Spring Boot app to Azure.

You can also ask questions and leave feedback on the Azure Spring Apps GitHub page.

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.

Course – LS (cat=Spring)

Get started with Spring and Spring Boot, through the Learn Spring course:

>> THE COURSE
res – REST with Spring (eBook) (everywhere)
Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.