Spring IOC Container
Traditionally, the flow of business logic depends on the statically defined objects and their dependents. This approach creates tightly coupled applications that are hard to extend or modify. But with IOC containers, the business logic depends on the object graph built by an IOC container.
So what is an IOC Container?
Inversion Of Control(IoC) is a design principle where objects define their dependencies through constructors or setters. And it is an IoC container’s responsibility to solve these dependency graphs. A well-known example of IoC container implementation is Spring Framework.
Spring Framework lets you define XML or annotation-based configuration for object dependencies and how they should resolve themselves.
For example, take a look at these code snippets. These snippets follow a traditional business logic flow.
public class Engine {
private String type;
public Engine(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
Code language: Java (java)
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public void drive() {
System.out.printf("Driving Car with %s engine", engine.getType());
}
}
Code language: Java (java)
public class TraditionalExample {
public static void main(String[] args) {
Engine engine = new Engine("petrol");
Car car = new Car(engine);
car.drive();
}
}
Code language: Java (java)
Here, The business logic is to drive the car. But we are the ones who are creating and assembling the car and engine objects. If you have to drive a car with a different engine, then you should come back to edit this snippet again.
But with IoC containers like spring, you can tell the container to create objects for you. And at any point in your business logic, you could ask for a specific object by its name or type.
First, you let the spring framework know how to build the objects. This step is usually done through XML configuration or @Bean definitions.
<?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 class="com.springhow.examples.basics.Engine" name="dieselEngine">
<constructor-arg value="diesel"/>
</bean>
<bean class="com.springhow.examples.basics.Car">
<constructor-arg ref="dieselEngine"></constructor-arg>
</bean>
</beans>
Code language: HTML, XML (xml)
And then, within your application, first initialize an IoC container, in this case, an Application Context. Then you can ask for appropriate objects by context.getBean() methods.
public class SpringIOCExample {
private static final ApplicationContext
context = new ClassPathXmlApplicationContext("basic-context.xml");
public static void main(String[] args) {
Car car = context.getBean(Car.class);
car.drive();
}
}
Code language: Java (java)
As you can see in this example, The actual business logic doesn’t contain any lines related to object creation. Here, The spring framework uses a concept called “Constructor Dependency Injection” to create objects and their dependencies.
So just by changing the “engine” bean definition, you could get different car behavior.
Further on this, you could create a Car interface and Engine interface so that You could provide different types of implementations. For example, a SportsCar running on DieselEngine or an All-Electric Sedan.