Intro to the Spring ClassPathXmlApplicationContext

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
.

Leave a Reply

Your email address will not be published.