Spring ApplicationContext

0

What is ApplicationContext?

ApplicationContext is the spring’s central interface to provide configuration for an application.

It internally creates a BeanFactory, configures it for us and does additional things which are very in an application’s lifecycle. In this article, I will go through some of these additional pieces.

In the below diagram all the boxes in blue are the additional stuff that ApplicationContext takes care of and the grey boxes are what BeanFactory handles.

ApplicationContextAwareProcessor and Environment beans

  • ApplicationContext ¬†automatically adds a BeanPostProcessor to the container called ApplicationContextAwareProcessor. Beans which implement ApplicationContextAware are scanned and setApplicationContext() is invoked to set the context.
  • ApplicationContext automatically registers the environment beans for us. Below is a context file doesn’t contain any environment specific beans but we still can access those beans.

springDemoContext.xml

<beans>

    <bean id="testBean" class="springdemo.TestBean"/>

    <bean id="beanPostProcessor" class="springdemo.TestBeanProcessor"/>

    <bean id="beanFactoryPostProcessor" class="springdemo.TestBeanFactoryProcessor"/>

</beans>

Test case

    @Test
    public void testAppContext() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("springDemoContext.xml");
        assertTrue(ctx.containsBean("environment"));
        assertTrue(ctx.containsBean("systemProperties"));
        assertTrue(ctx.containsBean("systemEnvironment"));
    }

MessageSource

ApplicationContext automatically registers bean messageSource for you. It helps in internationalization for messages. The other way to access it by implementing MessageSourceAware.

ApplicationEventMulticaster

If there any registered application listeners that implement ApplicationListener, as and when an application event occurs, it will automatically be published to these registered listeners.

Instantiates non-lazy Singleton

The default behavior for ApplicationContext implementations is to eagerly pre-instantiate all singleton beans at startup whereas in case of BeanFactory it will instantiate only when you call getBean(). Any issues with bean configuration, we will come to know as soon as the context is created instead of coming to know at runtime.

Lifecycle Flow

Just to summarize with an example, I have here a TestBean that implements all the important interfaces and then I create an ApplicationContext. In each callback method I have a system output to trace the lifecycle flow from creation to closure of the context. If you want to see the bean’s lifecycle diagram click here.

  • BeanNameAware
  • BeanClassLoaderAware
  • ApplicationContextAware
  • BeanFactoryAware
  • Lifecycle
  • ApplicationListener
  • DisposableBean
  • InitializingBean

TestBean

package springdemo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;

import org.springframework.context.*;

public class TestBean implements BeanNameAware, BeanClassLoaderAware, ApplicationContextAware, BeanFactoryAware,
        Lifecycle, ApplicationListener, DisposableBean, InitializingBean {
    String name;

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

    ApplicationContext context;
    ClassLoader beanClassLoader;
    String beanName;
    BeanFactory beanFactory;

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("Configure bean: set ApplicationContextn");
        context = applicationContext;
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("Configure bean: set Bean's classLoadern");
        beanClassLoader = classLoader;
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Configure bean: set Bean namen");
        beanName = name;
    }

    public ApplicationContext getContext() {
        return context;
    }

    public ClassLoader getBeanClassLoader() {
        return beanClassLoader;
    }

    public String getBeanName() {
        return beanName;
    }

    @Override
    public void setBeanFactory(BeanFactory factory) throws BeansException {
        System.out.println("Configure bean: set Bean factoryn");
        beanFactory = factory;
    }

    @Override
    public void start() {
        System.out.println("start " + getBeanName() + "n");
    }

    @Override
    public void stop() {
        System.out.println("stop " + getBeanName() + "n");
    }

    @Override
    public boolean isRunning() {
        return true;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("bean " + beanName + " receives " + event.getClass() + "n");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("bean " + beanName + " destroyedn");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("bean " + beanName + " afterPropertiesSet is calledn");
    }
}

Test case below creates an application context and checks whether the default beans are loaded.

    @Test
    public void testAppContext() throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("/springdemo/springDemoContext.xml");
        assertTrue(ctx.containsBean("environment"));
        assertTrue(ctx.containsBean("systemProperties"));
        assertTrue(ctx.containsBean("systemEnvironment"));
        assertTrue(ctx.containsBean("messageSource"));
        assertTrue(ctx.containsBean("applicationEventMulticaster"));
        assertTrue(ctx.containsBean("lifecycleProcessor"));
    }

Output

bean factory post processor

Configure bean: set Bean name

Configure bean: set Bean's classLoader

Configure bean: set Bean factory

Configure bean: set ApplicationContext

bean testBean post processor before init

bean testBean afterPropertiesSet is called

bean testBean post processor after init

bean testBean receives class org.springframework.context.event.ContextRefreshedEvent

bean testBean receives class org.springframework.context.event.ContextClosedEvent

stop testBean

bean testBean destroyed
Share.

Leave A Reply