Recent Posts

Sunday, 9 June 2019

Inversion of Control

Inversion of Control [IOC]
     In general, in enterprise application if we need any service in our application then we have to put request to the service provider, where service provider has to create the required service then service provider has to send that service to the respective application.
     In enterprise applications, Inversion of Control is a design pattern or a design principle, it will make service provider to identify the required services of the enterprise applications and it will make the service provider to create and inject the required services to the application without expecting any request from the application. IOC is available in the following two forms.
1.Dependency Lookup
2.Dependency Injection
1. Dependency Lookup
     In Dependency Lookup, Service Provider will create the services and maintained that services either in the registry Software's or in the containers, where we have to perform lookup operations in order to get the required services. There are two ways to get achieve Dependency lookup.
1. Dependency Pull
2. Contextualized Dependency Lookup

1. Dependency Pull
     In Dependency Pull, Service Provider will create services and it will keep that services in any registry software’s, where we have to perform lookup operation in order to get the required services, that is, pull the required services from registry software’s.
E.g.
   When we start application Servers like WebLogic, JBOSS, WebSphere and Glassfish, automatically, Application Servers will create Datasource object and Application Servers will keep that Datasource object in JNDI Server as per the server settings which we made in application Server. In this context, we have to perform lookup(--) operation over JNDI server on the basis of the logical name in order to get the required Datasource object.
    In RMI Applications, User defined Registry Application will create Remote object and it will keep that Remote object in RMIRegistry with a particular logical name, here to get the required Remote object in Client Application we have to perform lookup operation over RMIRegistry on the basis of the logical name.
2. Contextualized Dependency Lookup
     In this mechanism, Service Provider will create the services and manage services, in this context, we have to perform lookup operation in order to get the required services from Service Provider.
E.g.
     In general, in web applications, when we start application Server then container will recognize all the web applications and container will deploy all the web applications into the server, when web applications are deployed in server , container will create ServletContext object automatically and Container will manage ServletContext object, in this context, to get ServletContext object we have to use getServletContext() method from GenericServlet directly without using any reference variable, from ServletConfig object reference and from ServletRequest object reference, that is, performing lookup operation in Container to get ServletContext object.
 
2. Dependency Injection
     In this mechanism, Service Provider will create the services and inject the required services to the application directly without performing lookup operations and without getting request from client.
E.g.
     In web applications, when we submit request to a particular Servlet, Container will execute the requested Servlet by performing the Servlet life cycle actions like Servlet Loading, Servlet Instantiation, Servlet Initialization, Request Processing and Servlet Deinstantiation. In Servlet initialization phase, container will create ServletConfig object and Container will inject ServletConfig object to the Servlet program through init(--) method, in Request Processing phase, Container has to create request and response objects and Container has to inject request and response objects to the Servlet program through service() method. There are two ways to achieve dependency injection.
1. Constructor Dependency Injection
2. Setter Method Dependency Injection

1. Constructor Dependency Injection
     If we inject dependent values to the Bean object through Constructor then this type of Dependency Injection is called as "Constructor Dependency Injection".
     If we want to use constructor dependency injection in Spring applications, first we have to declare the respective parameterized constructor in the corresponding bean class then we have to declare that constructor arguments in spring configuration file by using the <constructor-arg> tags.
E.g.
package com.ashok.spring.core.bean.dependencyinjection.constructor.beans;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Employee {
   private String empName;
   private String empId;
   private String empAddress;
   private double salary;

   public Employee(String empName, String empId, String empAddress, double salary) {
      super();
      this.empName = empName;
      this.empId = empId;
      this.empAddress = empAddress;
      this.salary = salary;
   }

   @Override
   public String toString() {
      return "Employee [empName=" + empName + ", empId=" + empId + ", empAddress=" + empAddress + ", salary=" + salary
            + "]";
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   <bean id = "emp" class = "com.ashok.spring.core.bean.dependencyinjection.constructor.beans.Employee">
      <constructor-arg value = "Ashok Kumar"/>
      <constructor-arg value = "Emp0087"/>
      <constructor-arg value = "Bhimavaram"/>
      <constructor-arg value = "50000"/>
   </bean>
</beans>
package com.ashok.spring.core.bean.dependencyinjection.constructor.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ashok.spring.core.bean.dependencyinjection.constructor.beans.Employee;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class TestSpringApplication {
   @SuppressWarnings("resource")
   public static void main(String[] args) {
      String configFile = "/com/ashok/spring/core/bean/dependencyinjection/constructor/config/applicationContext.xml";
      ApplicationContext context = new ClassPathXmlApplicationContext(configFile);
      Employee emp = (Employee) context.getBean("emp");
      System.out.println(emp);
   }
}
Output
Employee [empName=Ashok Kumar, empId=Emp0087, empAddress=Bhimavaram, salary=50000.0]
2. Setter Method Dependency Injection
     If we inject dependent values to the Bean through setXXX() methods then it is called as "Setter Method Dependency Injection".
     To inject primitive values and String value to the bean object then we have to use "value" attributes in <property> or <constructor-arg> tags in beans configuration file, but, If we want to inject User defined data types, that is, Object reference values then we have to use "ref" attribute in <property> tag or in <constructor-arg> tag.
E.g
package com.ashok.spring.core.bean.dependencyinjection.setter.beans;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Employee {
   private String empName;
   private String empId;
   private String empAddress;
   private double salary;

   public String getEmpName() {
      return empName;
   }

   public void setEmpName(String empName) {
      this.empName = empName;
   }

   public String getEmpId() {
      return empId;
   }

   public void setEmpId(String empId) {
      this.empId = empId;
   }

   public String getEmpAddress() {
      return empAddress;
   }

   public void setEmpAddress(String empAddress) {
      this.empAddress = empAddress;
   }

   public double getSalary() {
      return salary;
   }

   public void setSalary(double salary) {
      this.salary = salary;
   }

   @Override
   public String toString() {
      return "Employee [empName=" + empName + ", empId=" + empId + ", empAddress=" + empAddress + ", salary=" + salary
            + "]";
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
   xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation = "http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
   <bean id = "emp" class = "com.ashok.spring.core.bean.dependencyinjection.setter.beans.Employee">
      <property name = "empName" value = "Ashok Kumar"/>
      <property name = "empId" value = "Emp0087"/>
      <property name = "empAddress" value = "Bhimavaram"/>
      <property name = "salary" value = "45000"/>
   </bean>
</beans>
package com.ashok.spring.core.bean.dependencyinjection.setter.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ashok.spring.core.bean.dependencyinjection.setter.beans.Employee;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class TestSpringApplication {
   @SuppressWarnings("resource")
   public static void main(String[] args) {
      String configFile = "/com/ashok/spring/core/bean/dependencyinjection/setter/config/applicationContext.xml";
      ApplicationContext context = new ClassPathXmlApplicationContext(configFile);
      Employee emp = (Employee) context.getBean("emp");
      System.out.println(emp);
   }
}
Output
Employee [empName=Ashok Kumar, empId=Emp0087, empAddress=Bhimavaram, salary=45000.0]
Different Types of Elements Injection
1. In Spring applications, if we want to inject User defined data types then we have to use either "ref" attribute in <property> and <constructor-arg> tags or we have to use <ref> nested tag under <property> and <constructor-arg> tags.

2. In spring applications, if we want to inject List of elements in beans then we have to declare the corresponding property as java.util.List and we have to provide values in configuration file by using <list> tag in <property> tag or in <constructor-arg> tag.

3. In Spring applications, if we want to inject Set of elements in Bean object then we have to declare the corresponding property as java.util.Set and we have to provide values in configuration file by using <set> tag under <property> tag or <constructor-arg> tag.

4. In Spring applications, if we want to inject Map of elements in Bean object then we have to declare the corresponding property as java.util.Map and we have to provide Key-Value pairs in configuration file by using <map> and <entry> tags under <property> tag or <constructor-arg> tag.

5. In Spring applications, if we want to inject Properties of elements in Bean object then we have to declare the corresponding property as java.util.Properties and we have to provide Key-Value pairs in configuration file by using <props> and <prop> tags under <property> tag or <constructor-arg> tag.
E.g
package com.ashok.spring.core.bean.dependencyinjection.collections.beans;

public class Address {
   private String street;
   private String city;
   private String country;

   public String getStreet() {
      return street;
   }

   public void setStreet(String street) {
      this.street = street;
   }

   public String getCity() {
      return city;
   }

   public void setCity(String city) {
      this.city = city;
   }

   public String getCountry() {
      return country;
   }

   public void setCountry(String country) {
      this.country = country;
   }

   @Override
   public String toString() {
      return "Address [street=" + street + ", city=" + city + ", country=" + country + "]";
   }
}
package com.ashok.spring.core.bean.dependencyinjection.collections.beans;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Student {
   private String sid;
   private String sname;
   private Address saddress;
   private List<String> squal;
   private Set<String> scourses;
   private Map<String, String> scoursesAndFaculty;
   private Properties scourseAndCost;

   public String getSid() {
      return sid;
   }

   public void setSid(String sid) {
      this.sid = sid;
   }

   public String getSname() {
      return sname;
   }

   public void setSname(String sname) {
      this.sname = sname;
   }

   public Address getSaddress() {
      return saddress;
   }

   public void setSaddress(Address saddress) {
      this.saddress = saddress;
   }

   public List<String> getSqual() {
      return squal;
   }

   public void setSqual(List<String> squal) {
      this.squal = squal;
   }

   public Set<String> getScourses() {
      return scourses;
   }

   public void setScourses(Set<String> scourses) {
      this.scourses = scourses;
   }

   public Map<String, String> getScoursesAndFaculty() {
      return scoursesAndFaculty;
   }

   public void setScoursesAndFaculty(Map<String, String> scoursesAndFaculty) {
      this.scoursesAndFaculty = scoursesAndFaculty;
   }

   public Properties getScourseAndCost() {
      return scourseAndCost;
   }

   public void setScourseAndCost(Properties scourseAndCost) {
      this.scourseAndCost = scourseAndCost;
   }

   @Override
   public String toString() {
      return "Student [sid=" + sid + ", sname=" + sname + ", saddress=" + saddress + ", squal=" + squal
            + ", scourses=" + scourses + ", scoursesAndFaculty=" + scoursesAndFaculty + ", scourseAndCost="
            + scourseAndCost + "]";
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="address"
        class="com.ashok.spring.core.bean.dependencyinjection.collections.beans.Address">
        <property name="street" value="APHB Colony" />
        <property name="city" value="Bhimavaram" />
        <property name="country" value="India" />
    </bean>

    <bean id="student"
        class="com.ashok.spring.core.bean.dependencyinjection.collections.beans.Student">
        <property name="sid" value="12345" />
        <property name="sname" value="Ashok Kumar" />
        <property name="saddress">
            <ref bean="address" />
        </property>
        <property name="squal">
            <list>
                <value>BSc Computers</value>
                <value>MCA</value>
            </list>
        </property>
        <property name="scourses">
            <set>
                <value>Core Java</value>
                <value>Adv Java</value>
                <value>Spring</value>
                <value>Hibernate</value>
            </set>
        </property>
        <property name="scoursesAndFaculty">
            <map>
                <entry key="Core Java" value="Ratan" />
                <entry key="Adv Java" value="Durga" />
                <entry key="Spring" value="Sriman" />
                <entry key="Hibernate" value="Naveen" />
            </map>
        </property>
        <property name="scourseAndCost">
            <props>
                <prop key="Core Java">1500</prop>
                <prop key="Adv Java">2000</prop>
                <prop key="Spring">3000</prop>
                <prop key="Hibernate">3000</prop>
            </props>
        </property>
    </bean>
</beans>
package com.ashok.spring.core.bean.dependencyinjection.collections.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ashok.spring.core.bean.dependencyinjection.collections.beans.Student;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class TestSpringApplication {
   @SuppressWarnings("resource")
   public static void main(String[] args) {
      String configFile = "/com/ashok/spring/core/bean/dependencyinjection/collections/config/applicationContext.xml";
      ApplicationContext context = new ClassPathXmlApplicationContext(configFile);
      Student emp = (Student) context.getBean("student");
      System.out.println(emp);
   }
}
Output
Student [sid=12345, sname=Ashok Kumar, saddress=Address [street=APHB Colony, city=Bhimavaram, country=India], squal=[BSc Computers, MCA], scourses=[Core Java, Adv Java, Spring, Hibernate], scoursesAndFaculty={Core Java=Ratan, Adv Java=Durga, Spring=Sriman, Hibernate=Naveen}, scourseAndCost={Spring=3000, Adv Java=2000, Hibernate=3000, Core Java=1500}]
Circular Dependency Injection
     In Spring applications, if more than one bean objects are depending on each other through constructor dependency injection then it is called as Circular Dependency Injection, which is not supported by Spring framework, it able to rise an exception like "org.springframework.beans.factory.BeanCurrentlyInCreationException".
E.g.
package com.ashok.spring.core.bean.dependencyinjection.circular.constructor.beans;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Branch {
   Student student;

   public Branch(Student student) {
      this.student = student;
   }

   public String getBranchName() {
      return "Bhimavaram";
   }
}
package com.ashok.spring.core.bean.dependencyinjection.circular.constructor.beans;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Student {
   Branch branch;

   public Student(Branch branch) {
      this.branch = branch;
   }

   public String getStudentName() {
      return "Ashok Kumar";
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean id="student"
        class="com.ashok.spring.core.bean.dependencyinjection.circular.constructor.beans.Student">
        <constructor-arg ref="branch" />
    </bean>
    <bean id="branch" class="com.ashok.spring.core.bean.dependencyinjection.circular.constructor.beans.Branch">
        <constructor-arg ref="student" />
    </bean>
</beans>
package com.ashok.spring.core.bean.dependencyinjection.circular.constructor.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ashok.spring.core.bean.dependencyinjection.circular.constructor.beans.Branch;
import com.ashok.spring.core.bean.dependencyinjection.circular.constructor.beans.Student;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class TestSpringApplication {
   @SuppressWarnings("resource")
   public static void main(String[] args) {
      String configFile = "/com/ashok/spring/core/bean/dependencyinjection/circular/constructor/config/applicationContext.xml";
      ApplicationContext context = new ClassPathXmlApplicationContext(configFile);
      Student student = (Student) context.getBean("student");
      System.out.println(student);
      Branch branch = (Branch) context.getBean("branch");
      System.out.println(branch);
   }
}
Output
org.springframework.beans.factory.BeanCurrentlyInCreationException"
     In Spring applications, if we want to resolve Circular Dependency Injection then we have to use Setter Method dependency Injection instead of Constructor Dependency Injection
E.g.
package com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Branch {
   Student student;

   public Student getStudent() {
      return student;
   }

   public void setStudent(Student student) {
      this.student = student;
   }
}
package com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class Student {
   Branch branch;

   public Branch getBranch() {
      return branch;
   }

   public void setBranch(Branch branch) {
      this.branch = branch;
   }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 <bean id="student"
  class="com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans.Student">
  <property name="branch" ref="branch" />
 </bean>
 <bean id="branch"
  class="com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans.Branch">
  <property name="student" ref="student" />
 </bean>
</beans>
package com.ashok.spring.core.bean.dependencyinjection.circular.setter.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans.Branch;
import com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans.Student;

/**
 * 
 * @author Ashok Kumar
 *
 */
public class TestSpringApplication {
   @SuppressWarnings("resource")
   public static void main(String[] args) {
      String configFile = "/com/ashok/spring/core/bean/dependencyinjection/circular/setter/config/applicationContext.xml";
      ApplicationContext context = new ClassPathXmlApplicationContext(configFile);
      Student student = (Student) context.getBean("student");
      System.out.println(student);
      Branch branch = (Branch) context.getBean("branch");
      System.out.println(branch);
   }
}
Output
com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans.Student@3224f60b
com.ashok.spring.core.bean.dependencyinjection.circular.setter.beans.Branch@63e2203c
Note:
     If we provide both Constructor dependency injection and Setter method dependency injection to a single bean then IOC Container will perform constructor dependency injection first at the time of creating Bean object , after that, IOC Container will perform Setter method dependency injection, that is, Constructor Dependency Injection provided values are overridden with setter method dependency injection provided values, finally, Bean object is able to manage Setter method dependency Injection provided values.
Difference between Constructor and Setter Dependency Injection
1. In Constructor dependency injection, dependent values injected through a particular constructor.
     In Setter method dependency injection, dependent values are injected through properties respective setXXX() methods.

2. In Constructor Dependency Injection readability is not good, because, in Constructor dependency injection we are unable to identify to which property we are injecting dependent values.
      In setter method Dependency injection Readability is very good, because, in Setter method Dependency injection we are able to identify that to property we are able to inject the dependent values.

3. In Constructor Dependency injection, dependency injection is possible when all dependent objects are getting ready, if dependent objects are not ready then Constructor dependency injection is not possible.
     In Setter method dependency injection, even though dependent values are not ready, Setter method dependency injection will be performed.

4. In case of constructor dependency injection, partial dependency injection is not possible, because, we have to access the constructor by passing the required no of parameter values.
     In case of setter method dependency injection, partial dependency injection is possible, because, we are able to access setXXX() method individually.

5. In case of constructor dependency injection, it is not simple to change the values in bean object.
     In case of Setter method dependency injection, it is very simple to change the values in bean object.

6. In Constructor dependency injection, for every change on values a new bean object is created, because, for every change we have to call constructor explicitly.
     In Setter method dependency injection, for every change on values new object is not created, because, for every change we can access setXXX() method explicitly.

7. Constructor dependency injection will make the bean object as "Immutable Object".
     Setter method dependency injection will make the bean object as "mutable Object".

8. If we provide both Constructor and setter method dependency injection to a single bean object then setter method dependency injection overrides constructor dependency injection, but constructor dependency injection is not overriding setter method dependency injection.

9. Constructor dependency injection not support circular dependency injection.
     Setter method dependency injection support circular dependency injection.

10. Constructor dependency injection will give guarantee for dependency injection.
Setter method dependency injection will not give guarantee for dependency injection.

11. In Spring applications, if we have more no of elements to inject then it is suggestible to use Constructor dependency injection instead of setter method dependency injection.

Next Tutorial : P-Namespace and C-Namespace

Previous Tutorial : Bean Post Processor

No comments:

Post a Comment