Application context in Spring

on waitingforcode.com

Application context in Spring

Previously we've told that Spring beans were living in application context. In this article we'll develop this idea and present application context more in detail.

More precisely, the article about autowired annotation in Spring was destined to dependency injection through @Autowired annotation. This time we'll approach the concept of application context. In the first part we'll see what is this famous context where all Spring-managed beans live. At the second part we'll see the classes responsible for context management. At the last part, we'll make some operations on it.

What is Spring's application context ?

As you already know, Spring manages the classes itself. These classes are called beans and are living inside Spring container. The basic version of beans handler is bean factory. Represented as implementations of org.springframework.beans.factory.BeanFactory interface, it's a container which initializes, configures and manages the beans. But usually it's not sufficient to use only BeanFactory in Spring application. It's there where application context emerges.

Application context is a kind of enterprise-oriented bean factory. As standard bean factory, it's a space where beans live. But unlike standard bean factory, application context provides a supplementary enterprise layer. How ? For example, by providing internationalization, converting service or event propagation. Generally, application context is preferred over bean factory. Its only default is memory consumption, bigger than in the case of bean factory because of supplementary services. If the memory usage is very critical part of your program (for example in applets or mobile environment), think more about using bean factory. Otherwise, in more standard application, application context should be used.

Spring's application context classes

The key part of application context in Spring is the interface org.springframework.context.ApplicationContext. It extends some other interfaces:
- org.springframework.core.env.EnvironmentCapable: used to mark that an object exposes an implementation of Environment interface. According to intereface's comment, it's mainly used to accomplish instanceof checks.
- org.springframework.beans.factory.ListableBeanFactory: interface ables to list all beans or only the beans corresponding to expected type.
- org.springframework.beans.factory.HierarchicalBeanFactory: supports hierarchical beans management.
- ">org.springframework.context.MessageSource: helps to resolve messages with support of internationalization.
- org.springframework.context.ApplicationEventPublisher: interface that permits to notify all classes listening to some application context's events.
- org.springframework.core.io.support.ResourcePatternResolver: strategy interface that helps to resolve an resource address (for example: classpath:/WEB-INF/web.xml) into org.springframework.core.io.Resource objects.

Implementation of all of these interfaces causes that application context is more functional than a simple bean factory. Let's see it in the case of org.springframework.web.context.support.XmlWebApplicationContext which can be used in web applications. This class extends an abstract class from the same package, AbstractRefreshableWebApplicationContext.

XmlWebApplicationContext overrides abstract method loadBeanDefinitions from AbstractRefreshableApplicationContext, used to read all beans. In this case, all beans are read from XML files through org.springframework.beans.factory.xml.XmlBeanDefinitionReader. Another interesting method, inherited from AbstractRefreshableWebApplicationContext, is postProcessBeanFactory. It's invoked after loading of all bean definitions and before their instantiation. AbstractRefreshableWebApplicationContext uses it to register request and session scopes, and environments beans. In additionally, this abstract class implements ConfigurableWebApplicationContext interface that defines servlet's context and locations configuration.

Another abstract class inherited indirectly by XmlWebApplicationContext is AbstractRefreshableApplicationContext. It has several methods to handle context refreshing. A class that handles events notification is org.springframework.context.support.AbstractApplicationContext, inherited indirectly by XmlWebApplicationContext. It contains a publishEvent method that sends an event (instance of ApplicationEvent class) to all listening objects.

But the central point where life cycle is handled, is public void refresh() throws BeansException, IllegalStateException method of AbstractApplicationContext class. By reading it, we can note that following operations are made:

  1. the context is prepared to be refreshed (property source initialization)
  2. the bean factory is prepared to be explored (classloader definition, basic beans register)
  3. beans post processing (postProcessBeanFactory method) is invoked
  4. message source (message management) is initialized
  5. event multicaster initialization (event multicaster is an object that dispatches events to appropriate listening objects)
  6. listeners registration
  7. instantiation of all remaining beans (for example: conversion service

In non-web environments, we can use standard application context, as FileSystemXmlApplicationContext, ClassPathXmlApplicationContext or GenericXmlApplicationContext.

Manipulating Spring's application context

The third part of this article is about the practice. We'll see how to: get an context inside one controller, retrieve some of beans configuration and resolve one message. Before coding that, we need to put the correct context configuration.












  
    
      classpath:messages
      classpath:errors
    
  
  
  

With this configuration we can write a test controller and one class, ApplicationContextProvider, which will hold an application context instance and return it on demand. After writting a code, we'll explain its way of working.

// controller, TestController.java
@Controller
public class TestController {

  @Autowired
  private ApplicationContext context;

  @RequestMapping(value = "/test", method = RequestMethod.GET)
  public String test() {
    LOGGER.debug("[TestController] Received application context :"+context);
    ApplicationContext providerContext = ApplicationContextProvider.getApplicationContext();
    LOGGER.debug("[TestController] Provider context is :"+providerContext);

    if (this.context == providerContext) {
    LOGGER.debug("[TestController] Both contextes are the same");
    }

    LOGGER.debug("[TestController] Message is :"+this.context.getMessage("testMessage", new Object[] {}, Locale.ENGLISH));
    return "test";
  }
}

// context provider, ApplicationContextProvider.java
@Component
public class ApplicationContextProvider implements ApplicationContextAware {

  private static ApplicationContext context;

  @Override
  public void setApplicationContext(ApplicationContext c) throws BeansException {
    context = c;
  }

  public static ApplicationContext getApplicationContext() {
    return context;
  }

}

ApplicationContext instance is managed by Spring. It's the reason why we can inject it into another Spring-managed bean (a controller in our case) with @Autowired annotation. This is the first way of getting the context inside another bean.

The second way is the ApplicationContextProvider class implementing org.springframework.context.ApplicationContextAware interface. Let's stop for a moment here. This interface should be implemented by every class which want to be notified about currently running ApplicationContext. One method must be defined in its implementations, void setApplicationContext(ApplicationContext applicationContext) throws BeansException. This method permits to set current ApplicationContext instance to use it later by the implementation. The context is passing to ApplicationContextAware implementations by org.springframework.context.support.ApplicationContextAwareProcessor, registered at AbstractApplicationContext class level. Note that ApplicationcontextAwareProcessor is also used to set bean factory or application's context environment. In these 2 cases, the classes must implement, respectively, EmbeddedValueResolverAware and EnvironmentAware interfaces from org.springframework.context package.

In our case, ApplicationContextAware implementation is a simple context provider. But in another uses, it could be an object which needs an access to another beans or context ressources. It's all about getting application context.

The last part to approach is message resolving with context getMessage method. In our message_en.properties file, declared in previous configuration snippet, message's template is testMessage=It's our test message with content. We should see that in log files.

By the way, we see it, like another important message that indicates context equality between object got from ApplicationContextProvider and @Autowired's one:

[TestController] Received application context :Root WebApplicationContext: startup date [Wed Apr 02 20:00:23 CEST 2014]; root of context hierarchy
[TestController] Provider context is :Root WebApplicationContext: startup date [Wed Apr 02 20:00:23 CEST 2014]; root of context hierarchy
[TestController] All contexts are the same
[TestController] Message is :It's our test message with content.

This article explained a little bit more the idea of beans life space. At its first part we saw the basic idea of application context and its difference with bean factory. After we discovered the classes composing application context concept. At the end, we shown the way of getting the context and explained very useful interface, ApplicationContextAware.

Share on: