Home » Enterprise Java » spring » IoC Spring Example

About Gilbert Lopez

Gilbert Lopez
Gilbert Lopez is an application developer and systems integration developer with experience building business solutions for large and medium-sized companies. He has worked on many Java EE projects. His roles have included lead developer, systems analyst, business analyst and consultant. Gilbert graduated from from California State University in Los Angeles with a Bachelor of Science degree in Business.

IoC Spring Example

In this post, we feature a comprehensive article about IoC Spring. We will discuss Inversion of Control and how it is applied in Spring.

1. IoC Spring – Introduction

Inversion of Control is an OOP design principle for writing code that is loosely coupled. The objective is to outsource certain responsibilities typically performed by a class to an external entity, such as a framework or container. The result is a software application that is configurable, modular, and therefore more easily maintained.

We usually speak of IoC as it relates to object creation and management. In Spring, this task is delegated to the IoC container.

The Spring IoC container uses information provided by configuration metadata to instantiate, build and manage objects. Configuration metadata is provided through one or more of the following sources:

  • XML files
  • Java configuration classes
  • Java annotations

In this article, we will give an example of each approach.

1.1 Tools Used in this Example

  • Eclipse IDE for Enterprise Java Developers Version: 2019-09 R (4.13.0)
  • Spring Tools 4 – for Spring Boot 

Spring Tools 4 for Spring Boot is a set of plugins for Eclipse that support building and running Spring Boot applications. You can add Spring Tools 4 to your existing Eclipse installation by going to the Eclipse Marketplace and searching for “Spring Tools 4”.

2. IoC Spring Example

2.1 Create the Spring Boot Project

We will be using Spring Boot for this example. In the New Project – Select a Wizard dialog box, expand Spring Boot and select Spring Starter Project. Click “Next”.

IoC Spring - New Project
New Project

In the New Spring Starter Project dialog box, enter a name for the project. Also, enter the group, artifact and package information. Accept all the other default values. Click “Next”.

IoC Spring - New Spring Starter Project
New Spring Starter Project

In the New Spring Starter Project Dependencies dialog window, click “Finish”. (We will not require any dependencies for this example.)

IoC Spring - Project Dependencies
Project Dependencies

2.2 Define the Interface and Classes

For this example, we will use a simple interface and two implementations. Create a new package com.javacodegeeks.examples.beans and interface Animal with following code:

Animal.java
public interface Animal {

	String getFavoritePastime();
}

Also, create two classes (Dog and Cat) that implement the Animal interface.

Dog.java
public class Dog implements Animal {

	@Override
	public String getFavoritePastime() {
		return "I like to bark!";
	}
}
Cat.java
public class Cat implements Animal {

	@Override
	public String getFavoritePastime() {
		return "I like to nap!";
	}
}

2.3 Application without IoC

Modify the IocSpringApplication class in the com.javacodegeeks.examples package and add the following code:

IocSpringApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import com.javacodegeeks.examples.beans.Animal;
import com.javacodegeeks.examples.beans.Dog;

@SpringBootApplication
public class IocSpringApplication {

	public static void main(String[] args) {
		SpringApplication.run(IocSpringApplication.class, args);
		
		Animal animal = new Dog();
		
		System.out.println(animal.getFavoritePastime());
	}

}

The class is creating an instance of Dog using its constructor and the new keyword. It has taken on the responsibility of managing its own objects. This approach leads to a tightly coupled class.

But what if we want to change the implementation of the Animal type to Cat? As it stands now, we will need to modify the class, since it controls the construction of the concrete class (Dog or Cat).

To make this code loosely coupled, we will have the framework control which implementation is to be used. This is Inversion of Control.

How does the framework decide which implementation to use? We need to configure the IoC container using metadata to assist in this regard. Let’s see how this can be accomplished.

2.4 XML Configuration

We can configure the Spring IoC container using XML files. Create an XML file in the src/main/resources directory and name it applicationContext.xml. (This is the naming convention, but you can name it anything you like.) This file will contain our configuration metadata. Add the following content to the file:

application.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" 
    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">

	
    <!-- Define your beans here -->
    
	<bean id="myAnimal" class="com.javacodegeeks.examples.beans.Dog" />

</beans>

The <beans> tag contains the required namespaces used for Spring IoC configuration.

You define your beans between the <beans> tags. The <bean> tag in this example has two attributes:

  • id – the name to use when referencing this bean
  • class – the fully qualified name of the concrete class for this bean

We are defining one bean (Dog) in this file. This bean will be created and managed by the IoC container instead of our class.

We can have one or more XML files that contain bean definitions. We specify the location of these resources using the @ImportResource annotation. Beans defined in the specified resource(s) will be registered in the IoC container when it is initialized. Add the @ImportResource annotation to the IocSpringApplication class as follows:

IocSpringApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

import com.javacodegeeks.examples.beans.Animal;
import com.javacodegeeks.examples.beans.Dog;

@SpringBootApplication
@ImportResource("classpath:/applicationContext.xml")
public class IocSpringApplication {

// some code...

}

In order to use our bean, we need to retrieve it from the ApplicatonContext. The static SpringApplication.run method returns the running ApplicationContext. Note the if we were using plain vanilla Spring instead of Spring Boot, we would need to instantiate the ApplicationContext ourselves, e.g. ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {" applicationContext.xml "}); .

Modify the the main method as follows:

IocSpringApplication.java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ImportResource;

import com.javacodegeeks.examples.beans.Animal;

@SpringBootApplication
@ImportResource("classpath:/applicationContext.xml")
public class IocSpringApplication {

	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(
			IocSpringApplication.class, args);
		
		Animal animal = context.getBean("myAnimal", Animal.class);
		
		System.out.println(animal.getFavoritePastime());
		
		context.close();
	}

}

   .

The interface org.springframework.context.ApplicationContext represents the Spring IoC container. (For the remainder of this article, the terms IoC container and application context will be used interchangeably.) ConfigurableApplicationContext is a subinterface of ApplicationContext and provides additional methods for configuring the IoC container. It also extends the Closeable interface, allowing us to close the application context, releasing any resources and destroying all cached singleton beans.

Now that we have a handle to the application context, we can retrieve the bean from the container using its bean id. We are using the overloaded ApplicationContext::getBean method that accepts the value of the bean id and the Java type as parameters to do this. By providing the type, we do not have to cast the return value, which provides a degree of type safety.

Save the change.  Right-click your project in Project Explorer and select Run As > Spring Boot App. You will see the following output in the console:

I like to bark!

If we want to use a different implementation for our Animal interface, we do not have to modify the class. We can change the implementation by simply editing the XML configuration file. Let’s change our application to use the Cat implementation for the Animal type. Modify the <bean> tag in applicationContext.xml as follows:

<bean id="myAnimal" class="com.javacodegeeks.examples.beans.Cat" />

Save the changes and rerun the application.  You will see the following output in the console:

I like to nap!

2.4 Java Configuration

We can also provide configuration metadata to the application context using Java configuration. With Java configuration, we no longer require XML to configure beans in the application.

A class that is annotated with @Configuration can serve as a source of bean definitions. You write methods inside the configuration class that instantiate and otherwise configure objects. These methods are then annotated with @Bean. This will register the beans in the application context, where they will be managed by the IoC container.  

Since @SpringBootApplication is meta-annotated with @SpringBootConfiguration, we can add our bean definitions directly in the IocSpringApplication class. (You may want to create your own configuration classes for this purpose.) Add the following method to IocSpringApplication:

IocSpringApplication.java
// other import statements
import com.javacodegeeks.examples.beans.Dog;

@SpringBootApplication
public class IocSpringApplication {
	
	@Bean
	public Animal dog() {
		return new Dog();
	}
// more code...
}

At this point, you may ask, what is the id of the defined bean? By default, the bean id is the name of the method. For example, the bean id for the Dog bean is “dog”. You can change the default bean id name by specifying the name attribute to the @Bean annotation, e.g. @Bean(name=“myDog”) or simply @Bean(“myDog”).

We will now update the class to use the configured bean. Change the main method as follows:

IocSpringApplication.java
	public static void main(String[] args) {
		ConfigurableApplicationContext context = SpringApplication.run(
			IocSpringApplication.class, args);
		
		Animal animal = context.getBean("dog", Animal.class);
		
		System.out.println(animal.getFavoritePastime());
		
		context.close();
	}

Finally, remove the @ImportResources annotation. We no longer require it. Save the file and rerun the application. You will see the following in the console:

I like to bark!

2.5 Annotation-Based Configuration

We can also provide configuration metadata using annotation-based configuration. During application startup, Spring will scan specific packages for Java classes annotated with @Component and other specialized annotations. This process is known as component scanning.

Here are some of the specialized (aka stereotype) annotations Spring will search for during the component scan process:

  • @Controller
  • @Service
  • @Repository

Spring will automatically register these annotated classes as beans in the application context.

Notes:

  • These specialized annotations are meta-annotated with @Component.
  • Any annotation that inherits from a stereotype annotation will also be registered in the application context.

You can specify the packages to be scanned with the @ComponentScan annotation. In a Spring boot application, the package containing the Spring Boot application class (e.g. IocSpringApplication in our example) and its sub-packages (e.g. com.javacodegeeks.examples.beans) will automatically get scanned.

Add the @Component annotation to the Dog class as shown:

Dog.java
@Component
public class Dog implements Animal {

	@Override
	public String getFavoritePastime() {
		return "I like to bark!";
	}
}

By default, the bean id is the name of the class in camel-case with the first character in lower-case. For example, the bean id for the Dog bean is “dog”. You can change the default bean id name by specifying the name attribute to the @Component annotation, e.g. @Component (name=“myDog”) or simply @Component (“myDog”).

Modify the IocSpringApplication  class by removing the @Bean method since it is now redundant. Save the changes and rerun the application.

3. Summary

In this article, we discussed Inversion of Control and how it is used to write code that is loosely coupled. We also demonstrated how IoC is used in Spring.

4. Download the Source Code

This was a IoC Spring Example.

Download
You can download the full source code of this example here: IoC Spring Example

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you our best selling eBooks for FREE!

 

1. JPA Mini Book

2. JVM Troubleshooting Guide

3. JUnit Tutorial for Unit Testing

4. Java Annotations Tutorial

5. Java Interview Questions

6. Spring Interview Questions

7. Android UI Design

 

and many more ....

 

Receive Java & Developer job alerts in your Area

 

Leave a Reply

avatar

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
Notify of