Last Updated on July 9, 2023 by KnownSense
IOC Container
Spring IoC (Inversion of Control) Container is the core of Spring Framework. It creates the objects, configures and assembles their dependencies, manages their entire life cycle. It receives instructions about the same from the provided configuration metadata. and uses Dependency Injection(DI) to manage the components that make up the application. Means for providing the configuration metadata can include Java annotations, Java code, or XML.
Since the Controlling of Java objects and their lifecycle is not done by the developers, hence the name Inversion Of Control.
There are 2 types of IoC containers:
- Core containers
- BeanFactory: BeanFactory holds bean definitions and instantiates them whenever asked for by the client application
- J2EE containers
- ApplicationContext: This the most powerful Container, compare to Bean-factory
- configurableApplicationContext: It is use in spring boot. One of the implementation of the ApplicationContext container. This container is used for Event Handling propose
That means if you want to use an IoC container in spring whether we need to use a BeanFactory or ApplicationContext or configurableApplicationContext. The BeanFactory is the most basic version of IoC containers, and the ApplicationContext extends the features of BeanFactory.
Dependency Injection
What is dependency? A dependency describes the relationship among activities and specifies the particular order in which they need to be performed.
For example: Before using a mobile we need to insert a SIM. So sim is a dependency for mobile.
Dependency Injection a programming technique in which an object or function receives other objects that it depends on instead of creating that object by itself.
It is the main functionality provided by Spring IOC(Inversion of Control). The Spring-Core module is responsible for injecting dependencies through either Constructor or Setter methods.
Types of Spring Dependency Injection:
There are two types of Spring Dependency Injection.
Setter DI | Constructor DI |
---|---|
The dependency will be injected with the help of setter methods. | The dependency will be injected with the help of constructor. |
Poor readability as it adds a lot of boiler plate codes in the application. | Good readability as it is separately present in the code. |
The bean must include getter and setter methods for the properties. | The bean class must declare a matching constructor with arguments. Otherwise, BeanCreationException will be thrown. |
Requires addition of @Autowired annotation, above the setter in the code and hence, it increases the coupling between the class and the DI container. | Best in the case of loose coupling with the DI container as it is not even required to add @Autowired annotation in the code. |
Circular dependencies or partial dependencies result with Setter DI because object creation happens before the injections. | No scope for circular or partial dependency because dependencies are resolved before object creation itself. |
Preferred option when properties are less and mutable objects can be created. | Preferred option when properties on the bean are more and immutable objects (eg: financial processes) are important for application. |
Why we need IoC and DI
- Maintainability: If your classes are loosely coupled and follow the single responsibility principle then your code will be easier to maintain.
- Testability: Loosely coupled classes that only do one thing — again, the natural result of using DI — are very easy to unit test. If you pass dependencies to classes, it’s quite simple to pass in a test double implementation. If dependencies are hard-coded, it’s impossible to create test doubles for those dependencies.
- Readability: Code that uses DI is more straightforward. It follows the single responsibility principle and, thus, results in smaller, more compact, and to-the-point classes.
- Flexibility: Small classes that do one thing can more easily be reassembled and reused in different situations.
- Extensibility: Code that uses dependency injection results in a more extendable class structure. By relying on abstractions instead of implementations, code can easily vary a given implementation.
- Team-ability: Since the code is loosely coupled, those implementations won’t rely on each other, and thus they are easily split between teams.