Dependency Injection and IOC
Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other objects with which they work) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies on its own by using direct construction of classes or the Service Locator pattern.
Advantages:
Code is cleaner with the DI principle, and decoupling is more effective when objects are provided with their dependencies. The object does not look up its dependencies and does not know the location or class of the dependencies. As a result, your classes become easier to test, particularly when the dependencies are on interfaces or abstract base classes, which allow for stub or mock implementations to be used in unit tests.
Traditional method:
public class Store {
private Item item;
public Store() {
item = new ItemImpl1();
}
}
By using Dependency Injection we can rewrite code as:
public class Store {
private Item item;
public Store(Item item) {
this.item = item;
}
}
Constructor-based Dependency Injection
In the case of constructor-based dependency injection, the container will invoke a constructor with arguments each representing a dependency we want to set.
The @Configuration annotation indicates that the class is a source of bean definitions. We can also add it to multiple configuration classes.
We use the @Bean annotation on a method to define a bean. If we don’t specify a custom name, then the bean name will default to the method name.
For a bean with the default singleton scope, Spring first checks if a cached instance of the bean already exists, and only creates a new one if it doesn’t. If we’re using the prototype scope, the container returns a new bean instance for each method call.
@Configuration
public class AppConfig {
@Bean
public Item item1() {
return new ItemImpl1();
}
@Bean
public Store store() {
return new Store(item1());
}
}
Setter Based Dependency Injection
For setter-based DI, the container will call setter methods of our class after invoking a no-argument constructor or no-argument static factory method to instantiate the bean. Let’s create this configuration using annotations:
@Bean
public Store store() {
Store store = new Store();
store.setItem(item1());
return store;
}
Feild Based Dependency Injection
In case of Field-Based DI, we can inject the dependencies by marking them with an @Autowired annotation:
public class Store {
@Autowired
private Item item;
}
This approach might look simpler and cleaner, but we don’t recommend using it because it has a few drawbacks such as:
This method uses reflection to inject the dependencies, which is costlier than constructor-based or setter-based injection.
It’s really easy to keep adding multiple dependencies using this approach. If we were using constructor injection, having multiple arguments would make us think that the class does more than one thing, which can violate the Single Responsibility Principle.
Difference between Setter Based and Constructor based DI:
Which to use when?
1. Constructor Injections
They are most useful when we need an object along with all its dependencies like for example – CAR can have various dependencies like engine, gear, steering and other relevant components without which a CAR is Use-Less. So, we need all those components wired together in the object of a car.
2. Setter Injections
They are preferred when we have some optional dependencies that are not mandatorily required but can assist in some ways. For example, let’s say we have a new user in our application and they have the freedom to set their profile picture, update personal info and other information whenever they want. Its completely optional.
Subscribe to my newsletter
Read articles from Mayank Singh directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by