Tuesday, August 3, 2010

Spring IoC Tutorial

I hope that you have read Spring MVC Tutorial as example explained here is with reference to the example used in Spring MVC Tutorial.

Inversion of Control (IoC) is one of the core feature of Spring. IoC uses Dependency Injection (DI) design pattern. The Spring framework provides container which injects dependencies while creating bean at runtime.

Let’s understand this by example. In Spring MVC example, let’s think LoginController class is dependent on another class/ bean LoginVerification to verify login details. Below is LoginVerification class which simply returns verification message from login details.

public class LoginVerification {

public LoginVerification(){

}

public String verifyLoginDtls(String username, String password){

if(username.equals(“arpita”) && password.equals(“arpita”))

return “Login Successful”;

else

return “Login Unsuccessful”;

}

}

As we want to verify login details, we will create object of LoginVerification inside LoginController to use its verifyLoginDtls method. Below is LoginController’s handleRequestInternal method.

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {

ModelAndView mv = new ModelAndView();

LoginVerification loginVerification = new LoginVerification();

String verificationMsg = loginVerification.verifyLoginDtls(request.getParameter(“username”) , request.getParameter(“password”));

mv.addObject(“resultMsg”, verificationMsg);

mv.setViewName(“resultPage”);

return mv;

}

This makes application components tightly coupled. Now, let’s see how we can avoid this by using DI. To do this, add below code in dispatcher-servlet.xml configuration file, we created in Spring MVC.

“loginVerification” class=“com.LoginVerification”/>

“loginController” class=“com.LoginController”>

“loginVerification” ref=“loginVerification”/>

So, now Spring IoC container will inject LoginVerification bean to LoginController bean when it creates LoginController bean and you can access LoginVerification bean directly in LoginController bean without creating its object like above. You can inject object ref using ‘ref’ attribute or can inject direct value, like “Login Successful”,”83”, using ‘value’ attribute. Now, let’s see how to access LoginVerification bean.

public class LoginController extends AbstractController {

private LoginVerification loginVerification;

// For Setter Injection

public LoginController(){

}

public void setLoginVerification(LoginVerification loginVerification){

this.loginVerification = loginVerification;

}

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {

ModelAndView mv = new ModelAndView();

String verificationMsg = loginVerification.verifyLoginDtls(request.getParameter(“username”), request.getParameter(“password”));

mv.addObject(“resultMsg”, verificationMsg);

mv.setViewName(“resultPage”);

return mv;

}

}

By this way, bean/ application component does not look up for its dependencies but framework provides them. In this way, DI helps in reducing coupling between the components.

There are three types of Dependency Injection.

  1. Setter Injection: Above example is of this type. It uses Setter method to inject required dependency. For each resource that is needed to be injected has setter method.
  2. Constructor Injection: In this type, an IoC container uses Constructor to inject required dependency. All the dependencies, whether they are simple values or references to other objects, are declared in the constructor. For example, say below is constructor.

Emp(int empNo, String empName){

this. empNo = empNo;

this.empName = empName;

}

Now, configuration file code is like,

“emp” class=“com.Emp”>

As there is only one constructor, above code will work fine but if there are two constructors, one like above and one with having two String arguments then ambiguity will occur. To avoid this confusion, add ‘type’ attribute which indicates type of value. Another scenario, if there are two constructors, one like above and second constructor having first argument String empName and second argument int empNo, then also confusion will occur and container may execute wrong constructor. This happens because the order in which the arguments appear in the bean configuration file will not be considered while invoking the constructor. To avoid this situation, use ‘index’ attribute. To solve above two scenarios, write like,

“emp” class=“com.Emp”>

3. Interface Injection: It provides the concrete implementations of an interface to the dependent object according to the configuration. Spring does not provide direct support for Interface Injection. However, using an auto-wiring service, one can make use of Interface Injection.

There is no specific rule to use particular DI method but Spring favors Setter Injection over Constructor Injection. The main difference between Constructor Injection and Setter Injection is that in Constructor Injection, the handing over of the dependencies takes place during instantiation of the dependent object, whereas with Setter Injection, it takes place after the dependent object is instantiated. One of the advantages of Constructor Injection is that all the dependencies are declared in one go. This also helps in understanding, on how many resources the class is depend on. The main difference between Interface Injection and the other two is that in Interface Injection, any of the implementations of the interface can be injected, whereas with the other two, the object of the class specified is injected.

Source Code Download. Jars are given in Spring MVC Tutorial.

No comments:

Post a Comment