Spring Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we'll look into the Spring ApplicationConext interface in detail.

2. The ApplicationContext Interface

One of the main features of the Spring framework is the IoC (Inversion of Control) container. The Spring IoC container is responsible for managing the objects of an application. It uses dependency injection to achieve inversion of control.

The interfaces BeanFactory and ApplicationContext represent the Spring IoC container. Here, BeanFactory is the root interface for accessing the Spring container. It provides basic functionalities for managing beans.

On the other hand, the ApplicationContext is a sub-interface of the BeanFactory. Hence, it offers all the functionalities of BeanFactory.

Furthermore, it provides more enterprise-specific functionalities. The important features of ApplicationContext are resolving messages, supporting internationalization, publishing events, and application-layer specific contexts. This is why we use it as the default Spring container.

3. What Is a Spring Bean?

Before we dive deeper into the ApplicationContext container, it's important to know about Spring beans. In Spring, a bean is an object that the Spring container instantiates, assembles, and manages.

So, should we configure all the objects of our application as Spring beans? Well, as a best practice, we should not.

As per Spring documentation, in general, we should define beans for service layer objects, data access objects (DAOs), presentation objects, infrastructure objects such as Hibernate SessionFactories, JMS Queues, and so forth.

Also, typically, we should not configure fine-grained domain objects in the container. It's usually the responsibility of DAOs and business logic to create and load domain objects.

So, let's define a simple Java class that we'll use as a Spring bean in this tutorial:

public class AccountService {

  @Autowired
  private AccountRepository accountRepository;

  // getters and setters
}

4. Configuring Beans in the Container

As we know, the primary job of the ApplicationContext is to manage beans.

So, an application must provide the bean configuration to the ApplicationContext container. Therefore, a Spring bean configuration consists of one or more bean definitions. Also, Spring supports different ways of configuring beans.

4.1. Java-Based Configuration

First, we'll start with Java-based configuration as it's the newest and the most preferred way of bean configuration. It's available from Spring 3.0 onward.

Java configuration typically uses @Bean-annotated methods within a @Configuration class. The @Bean annotation on a method indicates that the method creates a Spring bean. Moreover, a class annotated with @Configuration indicates that it contains Spring bean configurations.

So, let's now create a configuration class to define our AccountService class as a Spring bean:

@Configuration
public class AccountConfig {

  @Bean
  public AccountService accountService() {
    return new AccountService(accountRepository());
  }

  @Bean
  public AccountRepository accountRepository() {
    return new AccountRepository();
  }
}

4.2. Annotation-Based Configuration

Spring 2.5 introduced annotation-based configuration as the first step to enable bean configurations in Java.

In this approach, we first enable annotation-based configuration via XML configuration. Then, we use a set of annotations on our Java classes, methods, constructors, or fields to configure beans. Some examples of these annotations are @Component, @Controller, @Service, @Repository, @Autowired, and @Qualifier.

Notably, we also use these annotations with Java-based configuration. Also, Spring keeps on adding more capabilities to these annotations with each release.

So, now, let's see a simple example of this configuration.

First, we'll create the XML configuration, user-bean-config.xml, to enable annotations:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
  
  <context:annotation-config/>
  <context:component-scan base-package="com.baeldung.applicationcontext"/>

</beans>

Here, the annotation-config tag enables annotation-based mappings. Also, the component-scan tag tells Spring where to look for annotated classes.

Second, we'll create the UserService class and define it as a Spring bean using the @Component annotation:

@Component
public class UserService {
  // user service code
}

And then, we'll write a simple test case to test this configuration:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/user-bean-config.xml");
UserService userService = context.getBean(UserService.class);
assertNotNull(userService);

4.3. XML-Based Configuration

Finally, let's take a look at XML-based configuration. It's the traditional way of configuring beans in Spring.

Obviously, in this approach, we do all bean mappings in an XML configuration file.

So, let's create an XML configuration file, account-bean-config.xml, and define beans for our AccountService class:

<?xml version="1.0" encoding="UTF-8"?>
<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="accountService" class="com.baeldung.applicationcontext.AccountService">
    <constructor-arg name="accountRepository" ref="accountRepository" />
  </bean>
	
  <bean id="accountRepository" class="com.baeldung.applicationcontext.AccountRepository" />
</beans>

5. Types of ApplicationContext

Spring provides different types of ApplicationContext containers suitable for different requirements. These are implementations of the ApplicationContext interface. So, let's take a look at some of the common types of ApplicationContext.

5.1. AnnotationConfigApplicationContext

First, let's see the AnnotationConfigApplicationContext class, which was introduced in Spring 3.0. It can take classes annotated with @Configuration, @Component, and JSR-330 metadata as input.

So, let's see a simple example of using the AnnotationConfigApplicationContext container with our Java-based configuration:

ApplicationContext context = new AnnotationConfigApplicationContext(AccountConfig.class);
AccountService accountService = context.getBean(AccountService.class);

5.2. AnnotationConfigWebApplicationContext

AnnotationConfigWebApplicationContext is a web-based variant of AnnotationConfigApplicationContext.

We may use this class when we configure Spring's ContextLoaderListener servlet listener or a Spring MVC DispatcherServlet, in a web.xml file.

Moreover, from Spring 3.0 onward, we can also configure this application context container programmatically. All we need to do is to implement the WebApplicationInitializer interface:

public class MyWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
    context.register(AccountConfig.class);
    context.setServletContext(container);

    // servlet configuration
  }
}

5.3. XmlWebApplicationContext

If we use the XML based configuration in a web application, we can use the XmlWebApplicationContext class.

As a matter of fact, configuring this container is like the AnnotationConfigWebApplicationContext class only, which means we can configure it in web.xml or implement the WebApplicationInitializer interface:

public class MyXmlWebApplicationInitializer implements WebApplicationInitializer {

  public void onStartup(ServletContext container) throws ServletException {
    XmlWebApplicationContext context = new XmlWebApplicationContext();
    context.setConfigLocation("/WEB-INF/spring/applicationContext.xml");
    context.setServletContext(container);

    // Servlet configuration
  }
}

5.4. FileSystemXMLApplicationContext

We use the FileSystemXMLApplicationContext class to load an XML-based Spring configuration file from the file system or from URLs. This class is useful when we need to load the ApplicationContext programmatically. In general, test harnesses and standalone applications are some of the possible use cases for this.

For example, let's see how we can create this Spring container and load the beans for our XML-based configuration:

String path = "C:/myProject/src/main/resources/applicationcontext/account-bean-config.xml";

ApplicationContext context = new FileSystemXmlApplicationContext(path);
AccountService accountService = context.getBean("accountService", AccountService.class);

5.5. ClassPathXmlApplicationContext

In case we want to load an XML configuration file from the classpath, we can use the ClassPathXmlApplicationContext class. Similar to FileSystemXMLApplicationContext, it's useful for test harnesses as well as for application contexts embedded within JARs.

So, let's see an example of using this class:

ApplicationContext context = new ClassPathXmlApplicationContext("applicationcontext/account-bean-config.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);

6. Additional Features of ApplicationContext

6.1. Message Resolution

The ApplicationContext interface supports message resolution and internationalization by extending the MessageSource interface. Furthermore, Spring provides two MessageSource implementations, ResourceBundleMessageSource and StaticMessageSource.

We can use the StaticMessageSource to programmatically add messages to the source. However, it supports basic internationalization and is more suitable for tests than production use.

On the other hand, ResourceBundleMessageSource is the most common implementation of MessageSource. It relies on the underlying JDK's ResouceBundle implementation. It also uses the JDK's standard message parsing provided by MessageFormat.

Now, let's see how can we use the MessageSource to read the messages from a properties file.

First, we'll create the messages.properties file on the classpath:

account.name=TestAccount

Second, we'll add a bean definition in our AccountConfig class:

@Bean
public MessageSource messageSource() {
  ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
  messageSource.setBasename("config/messages");
  return messageSource;
}

Third, we'll inject the MessageSource in the AccountService:

@Autowired
private MessageSource messageSource;

Finally, we can use the getMessage method anywhere in the AccountService to read the message:

messageSource.getMessage("account.name", null, Locale.ENGLISH);

Spring also provides the ReloadableResourceBundleMessageSource class, which allows for reading files from any Spring resource location and supports hot reloading of bundle property files.

6.2. Event Handling

ApplicationContext supports event handling with the help of the ApplicationEvent class and the ApplicationListener interface. It supports built-in events like ContextStartedEvent, ContextStoppedEvent, ContextClosedEvent, and RequestHandledEvent. Moreover, it also supports custom events for business use cases.

7. Conclusion

In this tutorial, we've discussed various aspects of the ApplicationContext container in Spring. We've seen different examples of how to configure Spring beans in an AppicationContext. Also, we've seen how to create and use different types of ApplicationContext.

As always, the complete code is available over on GitHub.

Spring bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
guest
0 Comments
Inline Feedbacks
View all comments