Tuesday, September 19, 2017

Spring tutorials- Dependency Injection


Spring 1- Dependency injection

      ·        Dependency Injection- Decouple dependency of two dependent objects. 
      ·        Dependency is not hard corded in the class; it has to be injected by an entity.
      ·        Spring does instantiation of objects and injects it to the class which requires 
            that object.
      ·        Here Drawing class has been separated and not worry about objects 
            being passed. Spring will create Triangle or Circle object and inject it to 
            Drawing class.
      ·        First it call setShape() and then it’ll call drawShape()



Spring 3- Factory Bean
      
      ·         Spring is a container/factory of beans. Instantiation/Destruction of bean objects by spring container.
      ·         Object which needs to be created calls Object factory to create an object. It’ll read a configuration file where all bean definitions are defined which returns newly created object and handed over to object which needs newly created object.



      ·         Spring XML include definitions of beans and return object which is required.
      ·         Spring return singleton objects i.e. one instance till running application.


Spring 4- Writing Code using Bean Factory

Here, instead of creating Triangle object directly, we’re asking spring factory to instantiate object using spring.xml where definition is defined.

public class SpringDemo1 {
      public static void main(String[] args) {
            BeanFactory factory =new XmlBeanFactory(new FileSystemResource
            ("Spring.xml"));
            Triangle triangle  =(Triangle)factory.getBean("triangle");
            triangle.draw();
      }
}

Or

2) ClassPathResource resource = new ClassPathResource("beans.xml");
3) XmlBeanFactory factory = new XmlBeanFactory(resorce);

Bean Class- Triangle

public class Triangle {

     void draw(){
          System.out.println("Triange drawn");
     }
}

Spring.xml

Here ID is mapped with class and same id is being used by factory class to identify which object to be instantiate.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>
        <bean id="triangle" class="com.javadsalgo.basics.Triangle"/>
</beans>

Output
INFO: Loading XML bean definitions from file [C:\Users\paras.chawla\workspace\LetsCodeThinkCode\SpringTutorialBasics\Spring.xml]
Triangle drawn

Spring 5- Writing Code using ApplicationContext and specifying properties

Here, instead of using BeanFactory, we’re using ApplicationContext class which has multiple advantages. We can set object properties within bean definition as well.

public class SpringDemo2 {
     public static void main(String[] args) {
          ApplicationContext context =
          new ClassPathXmlApplicationContext("spring.xml");
          Triangle triangle =(Triangle)context.getBean("triangle");
          triangle.draw();
     }
}


Bean class- Triangle bean with properties defined

public class Triangle {
    
     String type;
    
     public String getType() {
          return type;
     }

     public void setType(String type) {
          this.type = type;
     }

     void draw(){
          System.out.println("Triange drawn and type is "+ getType());
     }
}

Spring.xml – triangle defined with its instance variables pre-instantiated. Spring will give object along with its value creation.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>
        <bean id="triangle" class="com.javadsalgo.basics.Triangle">
          <property name="type" value="Equilateral"/>
        </bean>
</beans>

Spring framework calling setter methods implicitly to instantiate the Object.

Spring 6- Writing Code using ApplicationContext using Constructor injection

Instead of using setter injection and initializing object using setter injection, we can use constructor injection to inject values in an Object.

public class Triangle {
    
     int height;
     String type;
    
     private Triangle(String type) {
          System.out.println("Constructor invoked with
     type variable");
          this.type = type;
     }
    
     private Triangle(String type, int height) {
          System.out.println("Constructor invoked with
     type and height variables");
          this.type = type;
          this.height=height;
     }

     public String getType() {
          return type;
     }

     /*public void setType(String type) {
          this.type = type;
     }
      */
     void draw(){
          System.out.println("Trianlge drawn and type
          is "+ getType()+"Height is "+ getHeight());
     }

     public int getHeight() {
          return height;
     }
}

Spring.xml

<beans>
          <!--Initialize Triangle object using Setter injection
        <bean id="triangle" class="com.javadsalgo.basics.Triangle">
          <property name="type" value="Equilateral"/>
        </bean>
        -->
       
        <!--Initialize Triangle object using Constructor injection-->
        <bean id="triangle" class="com.javadsalgo.basics.Triangle">
          <constructor-arg value="Equilateral"/>
          <constructor-arg value="20"/>
        </bean>
</beans>

constructor-arg  value=””

Spring 7- Writing Code using ApplicationContext using Object injection

     ·        Injecting an Object A while creating Object B which is having Object B as a reference.
     ·        We can have multiple Point Objects for Triangle example.
     ·        We’ll create 3 point objects in spring.xml and initialize with value as well using property tag.



     
     ·    Within Triangle bean, we can initialize triangle bean and give reference to Point beans, so it’ll create bean first and then inject to triangle bean.

     ·  We don’t need to create Point beans using new operator, spring will create beans once triangle require Point beans by itself.

public class SpringObjectInjector {
     public static void main(String[] args) {
          ApplicationContext context =
          new ClassPathXmlApplicationContext("spring.xml");
         
          Triangle1 triangle =(Triangle1)context.getBean("triangle");
          triangle.draw();
     }
}

Point.java

public class Point {

     int x,y;

     public int getX() {
          return x;
     }

     public void setX(int x) {
          this.x = x;
     }

     public int getY() {
          return y;
     }

     public void setY(int y) {
          this.y = y;
     }
}

Triangle.java

public class Triangle1 {

     Point point1;
     Point point2;
     Point point3;
     public Point getPoint1() {
          return point1;
     }
     public void setPoint1(Point point1) {
          this.point1 = point1;
     }
     public Point getPoint2() {
          return point2;
     }
     public void setPoint2(Point point2) {
          this.point2 = point2;
     }
     public Point getPoint3() {
          return point3;
     }
     public void setPoint3(Point point3) {
          this.point3 = point3;
     }
    
     public void draw(){
          System.out.println("Triangle with below points:");
          System.out.println("Point 1 "+getPoint1().getX()+
          " "+ getPoint1().getY());
          System.out.println("Point 2 "+getPoint2().getX()+
          " "+ getPoint2().getY());
          System.out.println("Point 3 "+getPoint3().getX()+
          " "+ getPoint3().getY());
     }
}

Spring.xml

<beans>      
        <bean id="pointA" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="0"></property>
          <property name="y" value="0"></property>
        </bean>
       
        <bean id="pointB" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="20"></property>
          <property name="y" value="10"></property>
        </bean>
       
       <bean id="pointC" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="40"></property>
          <property name="y" value="0"></property>
        </bean>
       
        <!--Initialize Triangle object using Object injection -->
    
<bean id="triangle" class="com.javadsalgo.basics.dto.Triangle1">
          <property name="point1" ref="pointA"></property>
          <property name="point2" ref="pointB"></property>
          <property name="point3" ref="pointC"></property>
</bean>
       
</beans>

Output

Triangle with below points:
Point 1 0 0
Point 2 20 10
Point 3 40 0

Spring 8- Inner Bean, aliases and idref
      
      ·        Inner Bean is useful when some beans are only required in defining one particular bean and not used elsewhere.
Eg. Point2 and Point3 beans used in defining Triangle bean and not used elsewhere where Point1 can be taken as separate bean

     ·        Aliases- We can give multiple names to same id/bean and can access bean by alias –name

<alias name=”triangle” alias=”triangle-alias”/>

     ·        zeroPoint is a common point where as  point2 and point3 must not be used elsewhere , so we can put point2 and point3 within triangle bean

<beans>
    

     <bean id="pointA" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="0"></property>
          <property name="y" value="0"></property>
     </bean>

<! -- Using inner beans, point2 and point3 used within triangle bean definition whereas point1 can be used in other places as well -->
     <bean id="triangle" class="com.javadsalgo.basics.dto.Triangle1">
          <property name="point1" ref="pointA"></property>
          <property name="point2">
              <bean class="com.javadsalgo.basics.dto.Point">
                   <property name="x" value="20"></property>
                   <property name="y" value="10"></property>
              </bean>
          </property>
          <property name="point3">
              <bean id="pointC”
                    class="com.javadsalgo.basics.dto.Point">
                   <property name="x" value="40"></property>
                   <property name="y" value="0"></property>
              </bean>
          </property>
     </bean>
    
<!-- Creating alias of a bean . Alias based on id not on name -->
<alias name="triangle" alias="triangle-alias"/>
</beans>

Spring 18 – Introduction to Annotations and RequiredAnnotation

public class SpringCircleRequiredAnnotation {
     public static void main(String[] args) {
          ApplicationContext context = new
          ClassPathXmlApplicationContext("spring.xml");
          Circle circle = (Circle) context.getBean("circle");
          circle.draw();
     }
}

Circle class where center is a required field. In order to make it required, we can use @Required annotation and tell RequiredAnnotationBeanPostProcessor to work upon this annotation. If center not defined in spring.xml , it’ll give exception before circle.draw()

public class Circle {
    
     private Point center;
    
     public Point getCenter() {
          return center;
     }

     public void setCenter(Point center) {
          this.center = center;
     }

     public void draw(){
          System.out.println("Circle drawn. X cordinate is"
         + getCenter().getX()+ ", "+
          "Y cordinate is :"+getCenter().getY());
     }
}

Spring.xml

RequiredAnnotationBeanPostProcessor class post check all required fields that must be needed to instantiate an object.

<!-- Making sure that circle bean required center to initialize -->
      <bean id="circle" class="com.javadsalgo.basics.dto.Circle">
            <property name="center" ref="pointA"/>
      </bean>
     
      <!--Bean Post Processor throws exception if it finds required annotations -->
      <bean class="org.springframework.beans.factory.annotation.
                   RequiredAnnotationBeanPostProcessor"/>

public class SpringCircleRequiredAnnotation {
     public static void main(String[] args) {
          ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
          Circle circle = (Circle) context.getBean("circle");
          circle.draw();
     }
}

Result:
Circle drawn. X cordinate is0, Y cordinate is :0

Spring 10 – Bean Autowiring
Using auto wiring feature, we keep bean property name/id same as attribute name defined in POJO. In this way, we need not to define below properties required for Triangle.

<bean id="triangle" class="com.javadsalgo.basics.dto.Triangle1">
          <property name="point1" ref="pointA"></property>
          <property name="point2" ref="pointB"></property>
          <property name="point3" ref="pointC"></property>
</bean>
                                                                       
Reading spring.xml --> triangle bean ---> check all attributes of triangle in POJO and then check same name beans in xml

        <bean id="point1" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="0"></property>
          <property name="y" value="0"></property>
        </bean>
       
        <bean id="point2" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="20"></property>
          <property name="y" value="10"></property>
        </bean>
       
       <bean id="point3" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="40"></property>
          <property name="y" value="0"></property>
        </bean>
       
<!--Initialize Triangle object using autowiring byName -->

<bean id="triangle"   class="com.javadsalgo.basics.dto.Triangle1" autowire=”byName”>

</bean>

Autowire byType – 1 member variable  and 1 bean type
Autowire byConstructor – Constructor Injection
Bydefault – autowire – false
In real life, it’s very difficult to guess what spring is doing. Helpful for small amount of beans

Spring 19- Autowired Annotation

public class Circle {
    
     private Point center;
    
     public Point getCenter() {
          return center;
     }
     @Required
     @Autowired
     public void setCenter(Point center) {
          this.center = center;
     }

     public void draw(){
          System.out.println("Circle drawn. X cordinate is"
          + getCenter().getX()+ ", "+
          "Y cordinate is :"+getCenter().getY());
     }
}
               
Spring.xml – Naming bean id name as center same as attribute in class circle. By default what autowire does is it checks by type. If there is only type then name can be anything.
But when there are multiple beans defined, then to make sure only particular bean is to be called, we make the same name of bean id as attribute.

<bean id="center" class="com.javadsalgo.basics.dto.Point">
          <property name="x" value="0"></property>
          <property name="y" value="0"></property>
     </bean>
     <!-- Making sure that circle bean required
          center to initialize -->
     <bean id="circle" class="com.javadsalgo.basics.dto.Circle">
          <!-- <property name="center" ref="pointA"/> -->
     </bean>
    
     <!--Bean Post Processor throws exception if it finds
         required annotations -->
     <bean class="org.springframework.beans.factory.annotation.
                  RequiredAnnotationBeanPostProcessor"/>
     <bean class="org.springframework.beans.factory.annotation.
                  AutowiredAnnotationBeanPostProcessor"/>
    
<!-- Add all BeanPostProcessor at once    
<context:annotation-config/>
 -->
</beans>

Below helps in putting all BeanPostProcessor at once rather than putting all classes for particular annotation.

<context:annotation-config/>

public class SpringCircleAutowireAnnotation {
     public static void main(String[] args) {
          ApplicationContext context =
          new ClassPathXmlApplicationContext("spring.xml");
          Circle circle = (Circle) context.getBean("circle");
          circle.draw();
     }
}

Output

Circle drawn. X cordinate is0, Y cordinate is :0

Spring bean lifecycle
What type of transaction Management Spring support?
Following two type of transaction management is supported by spring:
1. Programmatic transaction management
2. Declarative transaction management.


No comments:

Post a Comment