What is IOC Container in Spring

In the previous article, we have seen the Installation Set up for running the Spring application you can check it here How to Setup the Environment to create Application in Spring?. In this article, we will understand the IOC Container.

Before looking at what is IOC Container let us look at a simple example in Spring. Follow the below steps to build the project in STS.

  • Open Spring Tool Suit which you just installed.
  • Click on File> Go to New > Other> Search Maven > Select Maven Project.

  • Click Next> Search Filter org.apache.maven.archetypes/webapp.

  • Click Next > Enter the GroupId & Archetype Id and click Finish.

  • Thus, your project is created. (These are the steps you have to follow while creating a project) .
  • Now, go to Browser and type Spring, 5 Maven. Go to Spring Core and copy the Latest dependencies in pom.xml. Also, add Spring Context Dependencies. I have given the pom.xml file here.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>New</groupId>
  <artifactId>FirstSpringApp</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>FirstSpringApp Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>5.3.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.4</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.3.3</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>

  <build>
    <finalName>FirstSpringApp</finalName>
    <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
      <plugins>
        <plugin>
          <artifactId>maven-clean-plugin</artifactId>
          <version>3.1.0</version>
        </plugin>
        <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
        <plugin>
          <artifactId>maven-resources-plugin</artifactId>
          <version>3.0.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>2.22.1</version>
        </plugin>
        <plugin>
          <artifactId>maven-war-plugin</artifactId>
          <version>3.2.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-install-plugin</artifactId>
          <version>2.5.2</version>
        </plugin>
        <plugin>
          <artifactId>maven-deploy-plugin</artifactId>
          <version>2.8.2</version>
        </plugin>
      </plugins>
    </pluginManagement>
  </build>
</project>
  • Now, we will create an Interface Phone which will have two methods calling() and sms(). There are two classes that are implementing the Interface Mobile are Samsung and Nokia.

Phone.java

package com.codedec.interfaces;

public interface Phone {

  void calling();

  void sms();
}

Samsung.java

package com.codedec.phones;

import com.codedec.interfaces.Phone;

public class Samsung implements Phone {

  @Override
  public void calling() {
    // TODO Auto-generated method stub
    System.out.println("Calling with Samsung");
  }

  @Override
  public void sms() {
    // TODO Auto-generated method stub
    System.out.println("Sending Messages using Samsung");
  }

}

Nokia.java

package com.codedec.phones;

import com.codedec.interfaces.Phone;

public class Nokia implements Phone{

  @Override
  public void calling() {
    // TODO Auto-generated method stub
    System.out.println("Calling using Nokia");
  }

  @Override
  public void sms() {
    // TODO Auto-generated method stub
    System.out.println("Sending Messages using Nokia");
  }

}
  • Now, create the App.java class to test this method.

App.java

In this class, First, we will make an Object of Samsung Class and call the calling() and sms() method.

package com.codedec;

import com.codedec.phones.Samsung;

public class App {

  public static void main(String[] args) {

    Samsung samsung = new Samsung();
    samsung.calling();
    samsung.sms();

  }
}
  • This is the following output
Calling with Samsung
Sending Messages using Samsung
  • This is the normal way in which we call method.  But, here we will just modify the main method and follow the Java Practice, and by using the Interface we will call the methods.
public static void main(String[] args) {

    Phone phone = new Samsung();
    phone.calling();
    phone.sms();

}
  • Now, If we want to call the Nokia class method, we just need to change the new Samsung() to the new Nokia() and hence, respective methods will be called.
  • But, consider if in future there is one more class we have to add like RedMi Phone So, we need to change the Object name from Samsung() to Redmi(). So, this is not the correct way to make the changes in the code. So, here comes the role of the Spring Framework.
  • Spring Framework creates an Object for us and we don’t need to worry about creating objects but How? The answer is It will be taken care of by IOC Container. But, first, let us see what is IOC.

What is IOC?

The Spring has a container where it will create an object, managed it, and configure it and here the process of creation of an Object goes from developer to Spring Framework. So, this process is known as Inversion of Control. It is one of the most important features of the Spring Framework.

Now, we as a developer don’t need to worry about creating Objects. Hurray!! we just need to write the Logic. Now, we will look at How it creates an object using IOC Container.

 What is IOC Container?

In Spring, there is a configuration file where all the classes are kept. Spring has a container called IOC Container where our application is deployed. Container reads the Configuration file and creates the Object of every class inside the container. These objects are nothing but the Spring Beans.

The Configuration or config files can be represented either in XML format or annotations. Now, In the project when we want to use IOC Container in the following ways:

  • Bean Factory
  • Application Context 

Bean Factory is an Interface provided by the container and it is defined in org.springframework.beans.factory.Beanfactory. It is a legacy class that provides the support of Inversion of Control.

The application context is an Interface provided by the container and it is defined in org.springframework.context.ApplicationContext. It is an advanced class and supports all the features of bean Factory plus its own advanced feature.

Note: It is recommended to use the Application Context Interface.

Let us get back to our example, Now we will create the Configuration File beans.xml and we will add the bean name as our class name.

beans.xml

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
  <bean id="samsung" class="com.codedec.phones.Samsung"></bean>
  <bean id="nokia" class="com.codedec.phones.Nokia"></bean>
</beans>
  • On line no:6, we have added the bean name Samsung with an id associated with it. Make Sure to add fully Qualified names of the class.
  • Now Go to App.java class and Create the object of Application Context. For ApplicationConext there are many Implementations available but we will use ClassPathXmlApplicationContext because we are using the config file as XML.

App.java

package com.codedec;

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

import com.codedec.interfaces.Phone;
import com.codedec.phones.Nokia;
import com.codedec.phones.Samsung;

public class App {

  public static void main(String[] args) {

    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Nokia n = context.getBean("nokia", Nokia.class);
    n.calling();
    n.sms();

  }
}
  • On line no:14, ApplicationContext will read the Config file and will create the Object of a class specified with the reference specified in id in beans.xml. 
  • Now to get the Object just write the getBean(“nokia”, Nokia. class) method and call the respective methods.

Now, we will use the Interface Phone to make the application more configurable. In beans.xml, just do the following changes.

<bean id="p" class="com.codedec.phones.Samsung"></bean>
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    Phone phone= (Phone) context.getBean("p",Phone.class);
    phone.calling();
    phone.sms();
}
  •  On line no: 3, we have used Interface Phone.java, and using this interface we have called the method of calling() and sms() method of Samsung class.
  • Just Run the App.java and see the following output.
Calling with Samsung
Sending Messages using Samsung

Thus, in the future also, if some new class is added we just need to add it to the config file and IOC Container will take care of creating Objects. Thus this is the importance of IOC Container in Spring Framework.

In the next article, we will see another important concept called Dependency Injection in Spring Framework.