Chapter 2. Inversion of Control in Spring

In this chapter, we'll explore the concept of Inversion of Control (IoC). We'll then explore Spring Core Container, BeanFactory, and ApplicationContext, and you will learn how to implement them. We will take a look at Dependency Injection (DI) in Spring and their types: setter and constructor. We will wire beans using setter- and constructor-based Dependency Injection for different data types. We will also go through bean definition inheritance in Spring. We will then see autowiring in Spring and their modes. We will also see Spring bean's scope and its implementation. Then, we will move on to the life cycle of Spring bean.

The following is a list of topics that will be covered in this chapter:

  • Understanding IoC
  • Spring Container
  • BeanFactory
  • ApplicationContext
  • Dependency Injection
  • Constructor-based Dependency Injection
  • Setter-based Dependency Injection
  • Bean definition inheritance
  • Autowiring in Spring
  • Bean's scope
  • Singleton
  • Prototype
  • Request
  • Session
  • Global-session
  • Spring bean life cycle
  • Initialization callback
  • Destruction callback

Let's understand Inversion of Control.

Understanding Inversion of Control

In software engineering, IoC is a programming technique in which object coupling is bound at runtime by an assembler object and is usually not known at compile time using static analysis.

IoC is a more general concept, whereas DI is a concrete design pattern.

IoC is a way of thinking; a mechanism is required to activate components that provide specific functionality, due to which IoC depends on DI. The IoC pattern inverts responsibility of the managing the life cycle from the application to the framework, which makes writing Java applications even easier. IoC makes your code more manageable, more testable, and more portable. IoC also keeps component dependencies, life cycle events, and configuration outside of the components.

Consider the following example: we have a Car class and a Vehicle class object. The biggest issue with the code is tight coupling between classes. In other words, the Car class depends on the vehicle object. So, for any reason, changes in the Vehicle class will lead to the changes in, and compilation of, the Car class too.

So let's put down the problems with this approach:

  • The biggest problem is that the Car class controls the creation of the vehicle object
  • The Vehicle class is directly referenced in the Car class, which leads to tight coupling between the car and vehicle objects

The following figure illustrates this:

Understanding Inversion of Control

If, for any reason, the vehicle object is not created, the whole Car class will fail in the constructor initialization stage. The basic principle of IoC stands on the base of the Hollywood principle: Do not call us; we'll call you.

In other words, it's like the Vehicle class saying to the Car class, "don't create me, I'll create myself using someone else".

The IoC framework can be a class, client, or some kind of IoC container. The IoC container creates the vehicle object and passes this reference to the Car class, as shown here:

Understanding Inversion of Control

What is a container

In software development terminology, the word "container" is used to describe any component that can contain other components inside it. For example, Tomcat is a web container to contain deployed WAR files. JBoss is an application server/container; it contains an EJB container, web container, and so on.

The container first creates the objects and then wires them together, after which it moves on to configure them, and finally manage their complete life cycle. It identifies the object dependencies, creates them, and then injects them into the appropriate objects.

So, we can think about a container as an intermediate who'll register vehicle and car objects as separate entities, create the vehicle and car objects, and inject the vehicle object into car.

Spring Container

Spring Container is the central component of the Spring Framework. Spring Container manages the life cycle of an application's bean, which will live within Spring Container. Spring Container is responsible for wiring an application's beans by associating different beans together. Spring Container manages the components of applications using DI. The configuration metadata, which can be represented in XML, Java annotations, or Java code, helps Spring Container to decide the object to initiate, configure, and assemble.

Let's take an example of Tomcat, which is a Servlet container. Tomcat creates the Servlet objects, which are required in order to run an application. While deploying an application, we configure all Servlets in an XML file. Tomcat reads this XML file, identifies the Servlet to be instantiated, and then creates the identified Servlet.

Spring is a container but not a container of Servlet. It is a container of beans and behaves as a factory of beans. So, we can have Spring Container and we can have as many objects as we want, as shown in the following diagram. Also, all these objects are managed by Spring Container. The container handles the instantiation of object, their whole life cycle, and finally their destruction too:

Spring Container

Beans

Beans are reusable software components that are managed by the Spring IoC container. It contains the properties, setter, and getter methods of a class.

The Spring IoC container is represented by the interface org.springframework.context.ApplicationContext, which is responsible for instantiating, configuring, and assembling beans. Beans are reflected in the configuration metadata used by a container. The configuration metadata defines the instruction for the container and the objects to instantiate, configure, and assemble. This configuration metadata can be represented in XML, Java annotations, or Java code. In this chapter, we will configure using XML, which has been the traditional format to define configuration metadata. Refer to Chapter 9, Inversion of Control in Spring – Using Annotation, which is available online, on instructing the container to use Java annotations by providing a small amount of the XML configuration.

XML-based bean configuration

The bean configuration information is stored in an XML file, which is used to create a bean definition using the <bean>...</bean> element. The bean definition contains the following metadata, which represents the configuration information of a bean:

  • A fully qualified class name that represents bean name
  • The behavioral configuration elements, such as scope, life cycle, and so on, describe the bean's behavior in the Spring IoC container.

The following code snippet shows the basic structure of the XML configuration of the metadata:

<?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="..." class="...">
         <!-- configuration for this bean here -->
   </bean>
   <!-- more bean definitions here -->

</beans>

The configuration files have <beans> as the root element. The beans element has all other individual beans configured using the <bean> tag. Every <bean> tag needs to specify a class attribute and can have an optional ID or name attribute. The ID attributes enforce uniqueness in naming the beans. The class attribute has the fully classified class name; for example, the src.org.packt.Spring.chapter2.Employee class can be configured as follows:

...
<bean id="employeeBean"
         class="src.org.packt.Spring.chapter2.Employee">
   </bean>
   ...

A reference of the Employee class instance is returned when the configuration file is loaded using the BeanFactory or ApplicationContext container, and employeeBean is accessed using the getBean (employeeBean) method. The Spring IoC container is responsible for instantiating, configuring, and retrieving your Spring beans. The Spring IoC container enforces DI in its various forms and employs a number of established design patterns to achieve this.

Spring provides the following two interfaces that act as containers:

  • BeanFactory: This is a basic container, and all other containers implement BeanFactory.
  • ApplicationContext: This refers to the subinterface of BeanFactory and is mostly used as a container in enterprise applications.

To instantiate Spring Container, create an object of any of the BeanFactory or ApplicationContext implementation classes that supply the Spring bean configuration. The basic packages in the Spring IoC container of the Spring Framework are org.springframework.beans and org.springframework.context. An advanced configuration mechanism is provided by the BeanFactory interface to manage any type of object. The ApplicationContext interface implements the BeanFactory interface, which provides enterprise-specific functionality and supports message-resource handling, Spring's AOP features, event publication, and WebApplicationContext for use in web applications.

Both the containers, BeanFactory and ApplicationContext, are responsible for providing DI. For all the configured beans, these containers act as a repository. These containers initiate a registered bean, populate the bean's properties, and call the init() method to make the bean ready for use. The destroy() method of bean is invoked during the shutdown of the application. The init() and destroy() methods reflect the Servlet life cycle, where initialization can be performed during the init() method and cleanup during the destroy() method.

BeanFactory

Spring creates all the instances, along with the references to the objects you require. This is different from when you create an instance yourself with the help of the new method. This is called a factory pattern.

What is a factory pattern?

In a factory pattern, we have an object that behaves as the object factory. Basically, if you need an instance of any object, you don't have to create the instance yourself. Instead, you call a method of this factory, which then returns the instance you wanted. This factory reads from a configuration file, which acts as a blueprint that contains guidelines on how we can create the object.

Assume that we have an object Foo and instead of creating a new object Bar, we make a call to another Java object, which is a Factory object. The job of the Factory object is to create and hand over a new object Bar to the object Foo, as shown in the following figure. The whole purpose of this factory is to produce objects.

What is a factory pattern?

The Factory object reads from the configuration, which has metadata with details about the object that needs to be created. Configuration is a blueprint of all those objects that Factory creates. The Factory object reads from this configuration file, as shown here:

What is a factory pattern?

The Foo object interacts with the Factory object to get an object with a certain specification. Then the Factory object finds out what the blueprint for that particular object specification is and then creates a new object, as shown in the following figure:

What is a factory pattern?

Once the object has been created, Factory hands back the requesting Bar object to the Foo object. So, now Foo will have a new object it wants not using new() but using Factory, as shown in the following figure. This is something that Spring does.

What is a factory pattern?

Spring BeanFactory

Spring has objects of the BeanFactory type that behave like the Factory object. You specify the blueprints object in a configuration file, which is an XML file, and then supply it to BeanFactory. Later, if you need the instance of any object, you can ask BeanFactory for it, which then refers to the XML file and constructs the bean as specified. This bean is now a Spring bean as it has been created by Spring Container and is returned to you. Let's now summarize this:

  1. Spring has BeanFactory, which creates new objects for us. So, the Foo object will call BeanFactory.
  2. BeanFactory would read from Spring XML, which contains all the bean definitions. Bean definitions are the blueprints here. BeanFactory will create beans from this blueprint and then make a new Spring bean.
  3. Finally, this new Spring bean is handed back to Foo, as shown here:
    Spring BeanFactory

The advantage here is that this new bean has been created in this BeanFactory, which is known by Spring. Spring handles the creation and the entire life cycle of this bean. So, in this case, Spring acts as container for this newly created Spring bean.

BeanFactory is defined by the org.springframework.beans.factory.BeanFactory interface. The BeanFactory interface is the central IoC container interface in Spring and provides the basic end point for Spring Core Container towards the application to access the core container service.

It is responsible for containing and managing the beans. It is a factory class that contains a collection of beans. It holds multiple bean definitions within itself and then instantiates that bean as per the client's demands.

BeanFactory creates associations between collaborating objects as they're instantiated. This removes the burden of configuration from the bean itself along with the bean's client. It also takes part in the life cycle of a bean and makes calls to custom initialization and destruction methods.

Implementation of BeanFactory

There are many implementations of the BeanFactory interface, with the org.springframework.beans.factory.xml.XmlBeanFactory class being the most popularly used one, which reads the bean definition and initiates them based on the definitions contained in the XML file. Depending on the bean definition, the factory will return either an independent instance or a single shared instance of a contained object.

This class has been deprecated in favor of DefaultListableBeanFactory and XmlBeanDefinitionReader, and the purpose of this implementation is just to explain BeanFactory. The constructor for XmlBeanFactory takes an implementation of the Resource interface as an argument, as shown in the following line of code:

XmlBeanFactory (Resource resource)

The Resource interface has many implementations. The two commonly used implementations are shown in the following table:

The Resource interfaces

Description

org.springframework.core.io.FileSystemResource

This loads the configuration file from the underlying filesystem

org.springframework.core.io.ClassPathResource

This loads the configuration file from the classpath

Let's assume that beans are configured in the beans.xml file located in the C drive:

...
<bean id="mybean" class="...">
  ...
</bean>
...

The code snippet to load the configuration file using BeanFactory is given as follows:

BeanFactory bfObj = new XmlBeanFactory (new FileSystemResource ("c:/beans.xml"));

MyBean beanObj= (MyBean) bfObj.getBean ("mybean");

Here, we've used FileSystemResource, which is one of the Resource interface implementations. The bfObj object corresponds to Spring Container, one that has loaded the bean definitions from the beans.xml file. BeanFactory is a lazy container, so at this point, only bean definitions get loaded, but beans themselves are not instantiated yet. At the second line, we call the getBean() method of the BeanFactory object created by passing the bean ID "mybean" as an argument to this method.

BeanFactory reads the bean definition of a bean with the ID "mybean" from Spring's beans.xml file, instantiates it, and then returns a reference.

The BeanFactory interface has different methods, such as getBean, containBean, and so on, for client code to call. You can get the complete list of these methods from http://docs.spring.io/spring/docs/2.0.x/reference/beans.html.

The BeanFactory container is usually used in very simple applications; however, in real-time projects, the ApplicationContext container is used.

ApplicationContext

Like BeanFactory, ApplicationContext is also used to represent Spring Container, built upon the BeanFactory interface. ApplicationContext is suitable for Java EE applications, and it is always preferred over BeanFactory. All functionality of BeanFactory is included in ApplicationContext.

The org.springframework.context.ApplicationContext interface defines ApplicationContext. ApplicationContext and provides advanced features to our Spring applications that make them enterprise-level applications, whereas BeanFactory provides a few basic functionalities. Let's discuss them:

  • Apart from providing a means of resolving text messages, ApplicationContext also includes support for i18n of those messages.
  • A generic way to load file resources, such as images, is provided by ApplicationContext.
  • The events to beans that are registered as listeners can also be published by ApplicationContext.
  • ApplicationContext handles certain operations on the container or beans in the container declaratively, which have to be handled with BeanFactory in a programmatic way.
  • It provides ResourceLoader support. This is used to handle low-level resources, Spring's Resource interface, and a flexible generic abstraction. ApplicationContext itself is ResourceLoader. Hence, access to deployment-specific Resource instances is provided to an application.
  • It provides MessageSource support. MessageSource, an interface used to obtain localized messages with the actual implementation being pluggable, is implemented by ApplicationContext.

Implementation of ApplicationContext

The most commonly used ApplicationContext implementations are as follows:

  • ClassPathXmlApplicationContext: This bean definition is loaded by the container from the XML file that is present in the classpath by treating context definition files as classpath resources. ApplicationContext can be loaded from within the application's classpath using ClassPathXmlApplicationContext:
    ApplicationContext context = 
    new ClassPathXmlApplicationContext("spring-beans.xml");
  • FileSystemXmlApplicationContext: This bean definition is loaded by the container from an XML file. Here, the full path of the XML bean configuration file should be provided to the constructor:
    ApplicationContext context = new FileSystemXmlApplicationContext("classpath:beans.xml");

    In the preceding code snippet, the ApplicationContext instance is created using the FileSystemXmlApplicationContext class and beans.xml is specified as a parameter.

    The getBean() method can be used to access a particular bean by specifying its ID, as shown in following code snippet:

    MyBean beanObj= (MyBean) context.getBean ("mybean");

    In the preceding code snippet, the getBean() method accepts the ID of the bean and returns the object of the bean.

    ApplicationContext is an active container that initiates all the configured beans as soon as the ApplicationContext instance is created and before the user calls the getBean() method. The advantage of this active creation of beans by ApplicationContext is the handling of exceptions during the startup of the application itself.

  • XmlWebApplicationContext: This is used to create the context in web application by loading configuration the XML file with definitions of all beans from standard locations within a web application directory. The default location of the configuration XML file is /WEB-INF/applicationContext.xml.
  • AnnotationConfigApplicationContext: This is used to create the context by loading Java classes annotated with the @Configuration annotation instead of XML files. The AnnotationConfigApplicationContext class is used when we define Java-based Spring bean configuration for the bean definition instead of XML files.
  • AnnotationConfigWebApplicationContext: This is used to create the web application context by loading the Java classes annotated with the @Configuration annotation instead of XML files in the web application.

To demonstrate an implementation of ApplicationContext, an example of PayrollSystem can be considered. It will have the EmployeeService interface, EmployeeServiceImpl class, and PayrollSystem class with the main method.

In the EmployeeService.java interface, you'll find the following code:

package org.packt.Spring.chapter2.ApplicationContext;

public interface EmployeeService {

   public Long generateEmployeeId();

}

The EmployeeService.java interface is a plain old Java interface that has a method named generateEmployeeId() to generate a unique employee ID on each call.

In the EmployeeServiceImpl.java class, you'll find the following code:

package org.packt.Spring.chapter2.ApplicationContext;

public class EmployeeServiceImpl implements EmployeeService {

   @Override
   public Long generateEmployeeId() {
          return System.currentTimeMillis();
   }
}

The EmployeeServiceImpl.java class implements the EmployeeService interface. This generateEmployeeId() class-implemented method is used to generate a unique employee ID on each part of this method based on the system's current time.

In the PayrollSystem.java class, you'll find the following code:

package org.packt.Spring.chapter2.ApplicationContext;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class PayrollSystem {

   public static void main(String[] args) {

         ApplicationContext context = new ClassPathXmlApplicationContext(
                      "beans.xml");

         EmployeeService empService = (EmployeeServiceImpl) context
                     .getBean("empServiceBean");
         System.out.println("Unique Employee Id: " + empService.generateEmployeeId());
   }

}

The PayrollSystem.java class is a main class that contains the main() method. This method creates an instance of ApplicationContext, calls the getBean() method to get the bean of EmployeeService, and then prints the generated unique employee ID by calling the method from this bean.

The beans.xml file contains the bean definition for EmployeeServiceImpl, as shown in the following code snippet:

...
<bean id="empServiceBean" class="org.packt.Spring.chapter2.ApplicationContext.EmployeeServiceImp">
</bean>
...

When you successfully run PayrollSystem.java, the output will be printed on the console as follows:

Unique Employee Id: 1401215855074

The generated Employee Id value will be different for you when you run the preceding code in your local system as it is based on the current time.

A Spring application requires several beans or objects to work together in order to develop a loosely coupled application. Objects depend on each other to carry out their respective functions and this applies to beans too. Now let's understand DI.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset