June 29, 2022

Spring IoC Container Types - ApplicationContext and BeanFactory

One of the main component of the Spring framework is the Spring IOC container which is responsible for instantiating beans, wiring dependencies and managing the bean lifecycle from its instantiation till destruction. The org.springframework.beans and org.springframework.context packages are the basis for SpringFramework’s IoC container. Based on these two packages

Spring containers are of two types-

  1. BeanFactory
  2. ApplicationContext

Spring BeanFactory

org.springframework.beans.factory.BeanFactory is the root interface for accessing a Spring bean container. Implementation of this interface provides object that hold a number of bean definitions, each uniquely identified by a String name.

A BeanFactory will load bean definitions stored in a configuration source, that configuration metadata is represented in XML, Java annotations, or Java code. For example XmlBeanFactory is an implementation of BeanFactory that reads bean definitions from an XML document.

Following diagram shows how Spring container works-

Spring IoC Container

Note that XmlBeanFactory class is deprecated from Spring 3.x and DefaultListableBeanFactory in conjunction with XmlBeanDefinitionReader should be used instead.

Spring BeanFactory example

In the example there is a class to place order called Order and purchase can be done from a retail store. In Order class dependency for store has to be injected. XML configuration is used for bean definition. Let’s see how BeanFactory is used to load bean definitions and to access those registered beans.

Bean classes

public interface OrderService {
  public void buyItems();
}
public class OrderServiceImpl implements OrderService {
  private IStore store;
  public OrderServiceImpl(IStore store){
    this.store = store;
  }

  public void buyItems() {
    store.doPurchase();
  }
}
public interface IStore {
  public void doPurchase();
}
public class RetailStore implements IStore {
  public void doPurchase() {
    System.out.println("Doing purchase from Retail Store");
  }
}
XML Configuration
<?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">
          
  <!-- Store bean --> 
  <bean id="store" class="com.knpcode.springproject.service.RetailStore" />           
  <!-- Order bean with dependencies -->
  <bean id="orderBean" class="com.knpcode.springproject.service.OrderServiceImpl">
    <constructor-arg ref="store" />
  </bean>
</beans>

Following class is used to create BeanFactory which reads the configuration to load bean definitions, wire dependencies and access those beans.

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import com.knpcode.springproject.service.OrderService;
import com.knpcode.springproject.service.OrderServiceImpl;

public class App {
  public static void main( String[] args ){
    // BeanFactory
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader  = new XmlBeanDefinitionReader(factory);
    // loading bean definitions
    reader.loadBeanDefinitions(new ClassPathResource("appContext.xml"));
    OrderService order = factory.getBean(OrderServiceImpl.class);
    order.buyItems();
  }
}
Output
17:51:24.668 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 2 bean definitions from class path resource [appContext.xml]
17:51:24.701 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orderBean'
17:51:24.736 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'store'
Doing purchase from Retail Store

Here ClassPathResource is used to read configuration from class path there is also a FileSystemResource to read configuration from file system.

Spring ApplicationContext

org.springframework.context.ApplicationContext is a sub-interface of BeanFactory and it adds more enterprise-specific functionality on top of the BeanFactory. Some of the important features added by ApplicationContext are-

  • Easier integration with Spring’s AOP features
  • Message resource handling (for use in internationalization)
  • Event publication to event listeners
  • Application-layer specific contexts such as the WebApplicationContext for use in web applications.

Spring documentation prefers usage of ApplicationContext over BeanFactory as it provides all the services of the BeanFactory plus the features as mentioned above. In a resource intensive application where even a slight reduction in memory usage matters BeanFactory can be used instead.

Spring framework has several implementations of the ApplicationContext interface. In standalone applications, it is common to create an instance of ClassPathXmlApplicationContext (to read XML residing in class path) or FileSystemXmlApplicationContext (full path of the XML file is provided to read it from file system).

In Web applications, XmlWebApplicationContext is used to provide configuration for a web application as a XML document.

Spring ApplicationContext example

For the example configuration as used above ApplicationContext can be instantiated as given below-

import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.knpcode.springproject.service.OrderService;
import com.knpcode.springproject.service.OrderServiceImpl;

public class App {
  public static void main( String[] args ){
    // create context using configuration
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    OrderService order = context.getBean("orderBean", OrderServiceImpl.class);
    order.buyItems();
    // close the context
    context.close();
  }
}

If you want to use FileSystemXmlApplicationContext then you have to pass file location as a relative path or absolute path.

FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("F:\\knpcode\\Spring WorkSpace\\SpringProject\\src\\main\\resources\\appContext.xml");

That's all for the topic Spring IoC Container Types - ApplicationContext and BeanFactory. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment