March 10, 2017

#Spring part 1 : Bean Factory, Property Initilization, Constructor Injection, Injecting Objects, Inner Beans, Aliases, Initializing Collections and Bean Autowiring

BeanFactory : It reads blue print of the file from the configuration files and return the instance of bean.

In the below example we will be using XmlBeanFactory.


1). create a Traingle class with draw() method.
public class Traingle {
    public void draw()
    {
        System.out.println("Drawing traingle..");
    }
}


2). In DrawingApplication, we will be creating the bean using BeanFactory.

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;

public class DrawingApplication {
    public static void main(String[] args) {   
        BeanFactory beanFactory=new XmlBeanFactory(new FileSystemResource("spring.xml"));
        Traingle traingle=(Traingle)beanFactory.getBean("traingle");
        traingle.draw();   
    }
}



When you execute DrawingApplication, it will call draw() method of Traingle.

3). create spring.xml in the root of the application.
 < ?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="traingle" class="com.spring.test.Traingle"/ >
 < /beans >  


PropertyInitilization with ApplicationContext : It is used to initialize the property of an object by specifying the value in the configuration XML.

1). Update the Traingle class, add the type.
public class Traingle {
    private String type;
   
    public void draw()
    {
        System.out.println("Drawing traingle..of type "+type);
    }
    //getters and setters of type   
}

2). In DrawingApplication, we will be using ApplicationContext to create the bean with the preset value of type.
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

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

3). create spring.xml in the classpath.
 < ?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="traingle" class="com.spring.test.Traingle" >
     < property name="type" value="isosceles" / >
     < /bean >
 < /beans > 

Constructor Injection : Constructors are used to set the member variable values for Spring beans.

Injecting string-based values : Suppose in Traingle class we declare a constructor, which takes 'type' as an argument and in spring.xml, constructor-arg declared which invokes this constructor.

constructor-arg has a type attribute , if you don't specify the type attribute, by default string type constructor will be invoked.

1).
public class Traingle {
    private String type;
    private int height;
  
    public Traingle(int height)
    {
        this.height=height;
    }
    public Traingle(String type)
    {
        this.type=type;
    }
    public Traingle(String type, int height)
    {
        this.type=type;
        this.height=height;
    }
    public void draw()
    {
        System.out.println("Drawing traingle..of type "+type+", with height="+height);
    }
    //getters and setters of type and height
}

2).
 < bean id="traingle" class="com.spring.test.Traingle" >
     < constructor-arg value="isosceles"/ >
 < /bean >


3).
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
Traingle traingle=(Traingle)context.getBean("traingle");


This will initialize the bean by calling the constructor which takes String as an argument.

Injecting primitive values: The Traingle has another paramatrized constructor which takes the integer height. Suppose you want to draw a triangle by specifying the height, then you need to add 'type' element in constructor-arg. e.g

 < bean id="traingle" class="com.spring.test.Traingle" >
     < constructor-arg value="20" type="int"/ >
 < /bean >


Whenever you call context.getBean("traingle"), it will invoke the constructor which takes integer height as an argument.

Traingle class has one more constructor, which takes int height and String type as an argument. Suppose you want to invoke this constructor, then you need to make changes in spring.xml
 < bean id="traingle" class="com.spring.test.Traingle" >       
     < constructor-arg value="20" type="int"/ >
     < constructor-arg value="isosceles" type="String"/ >
 < /bean > 


Injecting Objects : We can use dependency injection to inject an object dependency to a Spring bean. We will create a Point class, which has two variables x and y. As the Triangle has three points, we will make changes in our Triangle class.

1). Point Class
package com.spring.test;

public class Point {
    private int x, y;
    @Override
    public String toString() {
        return "x="+x+", y="+y;
    }
    //getters and setters for x and y
       
}


2). add three Points in Traingle class.
package com.spring.test;

public class Traingle {

    private Point pointA, pointB, pointC;
    public void draw()
    {
        System.out.println("Drawing traingle..pointA:"+pointA+", pointB:"+pointB+", pointC:"+pointC);
    }
    //getters and setters of pointA, pointB, pointC
}


3). In the spring.xml, we will define three different beans for three points. Then in the triangle bean, we will give reference of these beans.

 < ?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="traingle" class="com.spring.test.Traingle" >        
         < property name="pointA" ref="zeroPoint"/ >
         < property name="pointB" ref="point1"/ >
         < property name="pointC" ref="point2"/ >
     < /bean >
   
     < bean id="zeroPoint" class="com.spring.test.Point" >
         < property name="x" value="0"/ >
         < property name="y" value="0"/ >
     < /bean >
     < bean id="point1" class="com.spring.test.Point" >
         < property name="x" value="-20"/ >
         < property name="y" value="0"/ >
     < /bean >
     < bean id="point2" class="com.spring.test.Point" >
         < property name="x" value="0"/ >
         < property name="y" value="20"/ >
     < /bean >
 < /beans >


4).
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
Traingle traingle=(Traingle)context.getBean("traingle");
traingle.draw();


draw method will print:
Drawing traingle..pointA:x=0, y=0, pointB:x=-20, y=0, pointC:x=0, y=20

Inner Beans: Suppose in above example (Inserting Objects), point1 and point2 are only used for creating the triangle bean and are not used anywhere else. In such cases, we do not need to define bean definitions for point1 and point2 separately. Instead of this we will use inner bean.

In case of inner beans, 'id' is not required.

 < ?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="traingle" class="com.spring.test.Traingle" >
         < property name="pointA" ref="zeroPoint" / >
         < property name="pointB" >
             < bean class="com.spring.test.Point" >
                 < property name="x" value="-30" / >
                 < property name="y" value="0" / >
             < /bean >
         < /property >
         < property name="pointC" >
             < bean class="com.spring.test.Point" >
                 < property name="x" value="0" / >
                 < property name="y" value="20" / >
             < /bean >
         < /property >
     < /bean >

     < bean id="zeroPoint" class="com.spring.test.Point" >
         < property name="x" value="0" / >
         < property name="y" value="0" / >
     < /bean >
 < /beans >

Aliases :
We can give different names to the same bean by using Aliases. e.g:
 < alias name="traingle" alias="tgleAlias"/ >
This will create an Aliase for traingle bean. To get the traingle bean using Aliase:

Traingle traingle=(Traingle)context.getBean("tgleAlias");
Aliase can be given in the bean definition itself by using the 'name' property. e.g:

 < bean id="zeroPoint" class="com.spring.test.Point" name="zeroPointAlias" >
     < property name="x" value="0" / >
     < property name="y" value="0" / >
 < /bean >
   
idref:
The 'ref' attribute of the 'property' tag can point to 'id' or and 'aliase'. If you want to restrict it to ONLY id then idref can be used. e.g:

 < bean id="traingle" class="com.spring.test.Traingle" >
         < property name="pointA" idref="zeroPoint" / >
         < property name="pointB" >
             < bean class="com.spring.test.Point" >
                 < property name="x" value="-30" / >
                 < property name="y" value="0" / >
             < /bean >
         < /property >
         < property name="pointC" >
             < bean class="com.spring.test.Point" >
                 < property name="x" value="0" / >
                 < property name="y" value="20" / >
             < /bean >
         < /property >
     < /bean >
   
Since we have mentioned idref="zeroPoint", it will check if the bean with id =zeroPoint is available or not. If yes then it will refer to that bean, else through an exception.

Initializing Collections : It is used if the member variable is a collection.
1). Traingle class is updated, now instead of PointA, pointB and pointC, it has a list of Points.
package com.spring.test;

import java.util.List;

public class Traingle {
    private List < Point >  points;
    public void draw()
    {
        System.out.println("Drawing traingle..");
        points.forEach((point)- > System.out.println(point));
    }
    //getters and setter for points   
}


2). spring.xml need to be updated:
 < ?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="traingle" class="com.spring.test.Traingle" >
         < property name="points" >
             < list >
                 < ref bean="zeroPoint"/ >
                 < ref bean="point1"/ >
                 < ref bean="point2"/ >
             < /list >
         < /property >
     < /bean >    
     < bean id="zeroPoint" class="com.spring.test.Point" >
         < property name="x" value="0"/ >
         < property name="y" value="0"/ >
     < /bean >
     < bean id="point1" class="com.spring.test.Point" >
         < property name="x" value="-20"/ >
         < property name="y" value="0"/ >
     < /bean >
     < bean id="point2" class="com.spring.test.Point" >
         < property name="x" value="0"/ >
         < property name="y" value="20"/ >
     < /bean >
 < /beans > 


Bean Auto wiring : With this feature dependencies can be automatically wired, which in turn reduces the configuration that we need to do.

Suppose the Traingle class has pointA, pointB, pointC. If the name of beans in 'spring.xml' is same as member variables (in our case pointA, pointB, pointC), we can request Spring to use the auto wire feature by specifying autowire="byName".

 < ?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="traingle" class="com.spring.test.Traingle" autowire="byName"/ >    
     < bean id="pointA" class="com.spring.test.Point" >
         < property name="x" value="0"/ >
         < property name="y" value="0"/ >
     < /bean >
     < bean id="pointB" class="com.spring.test.Point" >
         < property name="x" value="-20"/ >
         < property name="y" value="0"/ >
     < /bean >
     < bean id="pointC" class="com.spring.test.Point" >
         < property name="x" value="0"/ >
         < property name="y" value="20"/ >
     < /bean >
 < /beans >


We can do the auto wire by type, this will work only if there is only 1 member variable in the bean and only 1 bean of each type. e.g only one Point member variable in Traingle and only one Point bean in spring.xml.

autowire by constructor does the constructor injection.

By default the autowire is off

-K Himaanshu Shuklaa..

No comments:

Post a Comment

RSSChomp Blog Directory