Inversion
of Control and Dependency Injection is a core design pattern of Spring
framework. IOC and DI design pattern is also a popular design pattern interview question in Java.
As the name suggest Inversion of control pattern Inverts responsibility
of managing the life cycle of the object e.g. creating an object,
setting their dependency etc from application to a framework, which
makes writing Java application even more easy. The programmer often
confused between IOC and DI, well both words used interchangeably in
Java world but Inversion of Control is a more general concept and Dependency Injection is a concrete design pattern. Spring framework provides two implementations of IOC container in the form of Application Context and BeanFactory which
manages life-cycle of bean used by Java application. As you may know,
necessity is the mother of invention, it benefits to first understand
problem solved by IOC and Dependency Injection design pattern. This
makes your understanding more clear and concrete.
We have touched basics of Dependency Injection and Inversion of control in our article 10 OOPS and SOLID design principles for Java programmer and this Java article tries to explain it by taking a real life example of Service based architecture popular in enterprise Java development.
In this Spring or design pattern tutorial we will first see normal implementation of AutditService class, a class in this example which provides auditing in enterprise Java application and than use of dependency Injection. This will allow us to find out problems and how they are solved by Dependency injection design pattern. .
Also there are multiple way to inject dependency in spring e.g. Setter Injection or Constructor Injection, which uses setter method and constructor for injecting dependency, see Setter injection vs Constructor injection to find out when to use them.
We have touched basics of Dependency Injection and Inversion of control in our article 10 OOPS and SOLID design principles for Java programmer and this Java article tries to explain it by taking a real life example of Service based architecture popular in enterprise Java development.
In this Spring or design pattern tutorial we will first see normal implementation of AutditService class, a class in this example which provides auditing in enterprise Java application and than use of dependency Injection. This will allow us to find out problems and how they are solved by Dependency injection design pattern. .
Also there are multiple way to inject dependency in spring e.g. Setter Injection or Constructor Injection, which uses setter method and constructor for injecting dependency, see Setter injection vs Constructor injection to find out when to use them.
Inversion of Control and Dependency Injection design pattern
Any way let’s back to core concept of Inversion of Control and dependency Injection design pattern. Look at below implementation of an AuditService
whose job is to store every audit messages into database. This is one
of the simplest kind of auditing Service required in Enterprise Java
application.
/**
* Java Service class which provides auditing functionality by storing
* auditing message into persistent.
*/
public class AuditServiceImpl implements AuditService{
private AuditDAO auditDao = new AuditDAO();
@Override
public boolean audit (String message) {
return auditDao.store(message);
}
}
* Java Service class which provides auditing functionality by storing
* auditing message into persistent.
*/
public class AuditServiceImpl implements AuditService{
private AuditDAO auditDao = new AuditDAO();
@Override
public boolean audit (String message) {
return auditDao.store(message);
}
}
In first glance this implementation looks perfect but there are three major problem with this implementation:
1) Every AuditServiceImpl has its own copy of AuditDAO which is an expensive object as it wraps a database connection with in. It make no sense to create separate instances of AuditDAO, if you can share one between multiple AuditService.
2) AuditServiceImpl is closely coupled with AuditDAO as its creating instance of AuditDAO using new() operator. If you change the constructor of AuditDAO this code will be broken. Because of this coupling its difficult to replace AuditDAO with better implementation.
3) There is no easy way to test audit() method which is dependent on auditDAO. Since you can not mock AuditDAO you have to rely on actual implementation and if AuditDAO is an environmental dependent object which it is as it connect to different database on different environment, your Junit test case may pass in some environment and may fail in other environment.
What is Dependency Injection concept:
Dependency Injection is a design pattern on which dependency of object (in this case AuditDAO is a dependency for AuditServiceImpl Object) is injected by framework rather than created by Object
itself. Dependency Injection reduces coupling between multiple object
as its dynamically injected by framework. One of the implementation of
DI is Inversion of Control (IOC) on which framework like Spring controls
object’s dependency. There are mainly two types of Dependency Injection: Constructor Injection and Setter Injection.
In Constructor Injection, dependency of Object is injected using constructor, while in Setter Injection, Dependency is provided by setter method. Both
has there pros and cons. Constructor DI allows object to be created in
complete state and follows principle of fully functional object while
Setter DI allows object to be created without its dependency. which may
result in incomplete object if dependency is not available. This answers one of the famous spring interview question "when do you use Setter injection and Constructor Injection in Spring". Another benefit of Setter Dependency Injection is readability, since Spring is configured with xml configuration file
and setter injection is provided with bean property which is much
easier to read and understand than constructor injection which doesn't
state the property.
AuditServiceImpl written using Dependency Injection
Now we will see How Dependency Injection solves all three problems we have listed with above implementation of AuditService. here is a new implementation of AuditService with setter dependency injection.
public class AuditServiceImpl implements AuditService{
private AuditDAO auditDao;
public void setAuditDao(AuditDAO AuditDao) {
this.AuditDao = AuditDao;
}
@Override
public boolean audit (String message) {
return auditDao.store(message);
}
}
private AuditDAO auditDao;
public void setAuditDao(AuditDAO AuditDao) {
this.AuditDao = AuditDao;
}
@Override
public boolean audit (String message) {
return auditDao.store(message);
}
}
1. Since AuditDAO is injected here its possible to share single AuditDAO (an expensive object) between multiple AuditService.
2. Since AuditServiceImpl is not creating instance of AuditDAO its no more coupled with AuditDAO and work with any implementation of AuditDAO, thanks to another famous object oriented design principle “program for interface than implementation".
3. Because AuditDAO is injected by DI at runtime its easy to test audit() method by providing a mock AuditDAO
class. This not only makes testing easier but also independent of
environmental changes as you are not using actual implementation of AuditService.
This was the exact way I learn Dependency Injection and Inversion Of Control design principles. It always help first to understand problem and than solution to related each other. From above learning we can easily derive advantages or benefits of Dependency Injection in Java application:
1) Reduce coupling
both constructor and setter dependency injection reduce coupling. like in above example coupling between AuditService and AuditDAO is reduced by using Dependency Injection.
2) Improves testability
Dependency
Injection allows to replace actual object with mock object which
improves testability by writing simple JUnit tests which uses mock
object.
3) Flexibility
This is
another advantage which comes as side benefit of reduced coupling,
because of DI you can replace non performance implementation with better
one later.
That’s all on What is Inversion of control and Dependency Injection design pattern.
We have tried to learn this pattern with a real life example and
compares a class which is written using principle of IOC and DI and
without that. IOC and DI easily bring quality in coding. We have seen
clear benefits in terms of reduce coupling, improved testability and Flexibility
to change implementation. It’s always good to write code which follows
principle of Inversion of Control and dependency Injection and Spring
framework by default ensures that.
No comments:
Post a Comment