Sunday, July 23, 2017

Dependency Injection

DI:- passing needed dependencies into the object externally instead of having it construct them itself OR asking a factory object to make one of them.

class SomeClass{

MyObject myObject;
   public SomeClass(){
     myObject = factory.getObject();
   }

}

class SomeClass{

   public SomeClass(MyObject myObject){
     this.myObject = myObject;
   }

}

It allows us to remove hard-coded dependencies and make application loosely coupled, extendable and maintainable.

Eg. 
without DI:-
Switch needs to know beforehand which bulb I am connected to (hard-coded dependency). So,
Switch -> PermanentBulb //switch is directly connected to permanent bulb, testing not possible easily
with DI:-

Switch only knows I need to turn on/off whichever Bulb is passed to me. So,
Switch -> Bulb1 OR Bulb2 OR NightBulb (injected dependency)



Two types of Dependency Injection:

    Constructor Injection
    Setter Injection

1. Constructor-based dependency injection:
Constructor-based DI is accomplished when the container invokes a class constructor with a number of arguments, each representing a dependency on other class.


public class Triangle {

private String type;

public String getType(){
    return type;
 }

public Triangle(String type){   //constructor injection
    this.type=type;
 }
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
        <constructor-arg value="20"/>
</bean>

2. Setter-based dependency injection:
Setter-based DI is accomplished by the container calling setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean.


public class Triangle{

 private String type;

 public String getType(){
    return type;
  }
 public void setType(String type){          //setter injection
    this.type = type;
  }
 }

<!-- setter injection -->
 <bean id="triangle" class="com.test.dependencyInjection.Triangle">
        <property name="type" value="equivialteral"/>
</bean> 
 

NOTE: It is a good rule of thumb to 
Use Constructor Injection when object must be created with all of its dependency(mandatory dependencies).
Use Setter injection when a number of dependencies are more or you need readability(optional dependencies). 

Note that the if we use annotation based than @Required annotation on a setter can be used to make setters as a required dependencies.

If Object A and B are dependent on each other i.e A is depends on B and vice-versa. Spring throws ObjectCurrentlyInCreationException while creating objects of A and B because A object cannot be created until B is created and vice-versa. So spring can resolve circular dependencies through setter-injection. Objects constructed before setter methods invoked.

Another difference between setter vs constructor injection in Spring and one of the drawback of  setter injection is that it does not ensures dependency Injection. You can not guarantee that certain dependency is injected or not, which means you may have an object with incomplete dependency. On other hand constructor Injection does not allow you to construct object, until your dependencies are ready.

One more drawback of setter Injection is Security. By using setter injection, you can override certain dependency which is not possible with constructor injection because every time you call the constructor, a new object is gets created.


How do we implement DI in Spring Framework?

We can use Spring XML based(defined above) as well as Annotation based configuration to implement DI in spring applications.

@Autowired annotation is used to let Spring know that DI is required. This can be applied to field, constructor and methods level.

    //field-based dependency injection
    @Autowired
    private MessageService service;

    //constructor-based dependency injection  
    @Autowired
    public MyApplication(MessageService svc){
        this.service=svc;
    }
   
    //setter-based dependency injection
    @Autowired
    public void setService(MessageService svc){
        this.service=svc;
    } 


So, Dependency Injection is a design pattern, and @autowired is a mechanism for implementing it.
The DI idea is that, instead of your object creating an object it needs (say by using new to instantiate it), this needed object - a dependency - is handed to your object, typically using the constructor or a setter method.
If you autowire, you're injecting a dependency. In this case, Spring uses reflection to make this work, so you're not using the constructor or a setter method, but you're still injecting the dependency.

No comments:

Post a Comment

Web Development

Design Phase:- Below all these represent different stages of the UX/UI design flow:- Wireframes represent a very basic & visual repr...