What is Dependency Injection?
Dependency Injection is a concept used to eliminate dependencies from Java classes to make them easy to maintain and test. In the Spring Framework, Inversion of Control (IoC) is used to achieve dependency injection. Before moving any further into the topic, let’s understand what is a dependency.
What is a Dependency?
When one class instantiates an object of some other class, then it is said to be dependent on that class. This is referred to as tight coupling.
This type of dependencies can cause major issues while migrating to new environments or in case the structure of the depended class changes over the time.
Therefore, to avoid such kind of dependencies and to make the code loosely coupled, dependency injection is used.
What happens in Dependency Injection?
Instead of directly creating an instance of the other class, we acquire that instance, either as a constructor argument or as a method argument (such method is called as setter method).
These instances are passed as arguments through an external source such as XML files. This is known as Inversion of Control (IoC) and in Spring Framework it is achieved through an IoC container which is responsible for managing dependencies.
Advantages of Dependency Injection:
- The code becomes loosely coupled.
- Easy to maintain and test.
- Can be moved and executed in new environments without any issues.
Let’s see an example for dependency injection:
Class Circle { Square s; Circle() { s = new Square(); } /*void set() { s = new Square(); }*/ }
The above example illustrates the dependency of class Circle over the Square class which is called as tight coupling. We use either the constructor or the setter method to instantiate the Square class instance but not both.
The same code with the help of IoC can be re-structured as shown below:
Class Circle { Square s; Circle(Square s) { this.s = s; } /*void set(Square s) { this.s = s; }*/ }
Here the instance of the Square class is passed as an argument to its constructor and setter method and hence we can use it by invoking any one of them.
This makes the code loosely coupled and light weighted.
The IoC Container
In the Spring framework, the IoC container is responsible for objects instantiation and to manage dependencies among them.
We can implement the IoC container with the help of two interfaces:
- BeanFactory (org.springframework.beans.factory.BeanFactory)
- ApplicationContext (org.springframework.context.ApplicationContext)
The ApplicationContext
interface has some extra functionalities over the BeanFactory
, which helps in easy integration with the other Spring modules.
BeanFactory
Interface
There is a class XmlBeanFactory
which provides implementation to the BeanFactory
interface. The following example shows how to use BeanFactory
interface:
Resource R = new ClassPathResource("XMLFile.xml");
BeanFactory BF = new XmlBeanFactory(resource);
Here, the XmlBeanFactory
class takes a Resource object as parameter and hence we create a Resource object with the XML file name and pass it to the XmlBEanFactory
class.
ApplicationContext
Interface
There is a class ClassPathXmlApplicationContext
which provides implementation to the ApplicationContext
interface. The following example shows how to use ApplicationContext
interface:
ApplicationContext AC = new ClassPathApplicationContext("XMLFile.xml");
Here, the ClassPathXmlApplicationContext
class takes a string literal as a parameter, which should be the XML file name.
Dependency Injection using IoC and XML file
There are two ways of injecting dependencies:
- Constructor DI: The XML file through which we pass the class instances as parameters, contains instructions to invoke the constructor and pass the class instance as a constructor parameter.
- Setter Method DI: Here the XML file contains instructions to invoke the setter method and pass the class instance as the setter method parameter.
The XML file contains information of the class and its attributes whose instance we will use in our main
class.
The IoC container fetches the information from the XML file and will help to create an instance of that class in our main
class.