JOBS4TIMES jobs4timesLogo

Inversion Of Control (IOC) and Spring Core Container

Agenda :
  1. Inversion of Control (IoC)
  2. Dependency Injection (DI)
  3. Spring Containers
  4. Initializing Spring Core Container
  5. Types of Dependency Injection
  6. abstract attribute
  7. spring container based on FileSystemResource
  8. purpose of getBean() method
  9. lazy-init attribute
  10. What is Wiring
  11. Difference between id and name attributes
  12. ref tag
  13. Developing spring based application by using manual procedure
  14. Data Types of property tag
  15. Dependency Injection Example
  16. Configuring Beans
  17. Bean Scopes and LifeCycle
  18. Method Injection
  19. I18N applications in core module

Inversion of Control (IoC)

The advantage of Spring instead of developer create the object and establish the dependencies, the spring container create the object and establish the dependencies. This process is called as Inversion of Control(IOC).
  • IOC describes that a Dependency Injection needs to be done by an external entity(i.e., container) instead of creating the dependencies by the component itself.
  • Dependency Injection is a process of Injecting(Pushing) the dependencies into an object.
  • In general object is controlled by our java programmer, otherwise we can store the state of object using Serialization or Externalization.
  • If controlling of object is done by configuration files i.e. creating of object, storing state of object (i.e. somewhat inverse of way), this is called Inversion of Control.(IOC).

  • This IOC concept is base for every module of spring.
  • IOC is core in case of spring.
  • IOC is also called as Dependence Injection.
  • Here we are achieving dependency injection depending on object whatever the data requires, that will be injected through configuration file.
  • IOC container provides objects bases on the configuration in xml files. We are not creating object by using new operator for an entity. We will get object from IOC container. It goes to configuration file, based on that it generates object.
  • IOC container generates objects and it is giving those objects to our programmer.
  • IOC is maintains Singleton Object
Dependency Injection (DI)
Dependency Injection is a process which takes place when IOC getting perform because this reason we call Dependency Injection & IOC are same.
  • In developing huge systems using the object oriented programming methodology, we generally divide the system into objects where each of the objects represents some functionality.
  • In this case, the objects in the system use some other objects to complete the given response.
  • The objects with which our object collaborates to provide the services are known as its dependencies.
The traditional ways of obtaining the dependencies are by creating the dependencies or by pulling the dependencies using some factory classes and methods or form the naming registry.
But these approaches result in some problems which are
  • The complexity of the application increases.
  • The development time-dependency increases.
  • The difficulty for unit testing increases.
To solve these problem we have to use Push Model.
i.e., inject the dependent objects into our object instead of creating or pulling the dependent objects.

The process of injecting(pushing) the dependencies into an object is known as Dependency Injection (DI)

Spring Containers :

Core container or IOC container or BeanFactroy container

  1. Its an implementation class of an interface BeanFactory
  2. It supports lazy loading.
    • It means container will not create objects of configured pojo classes immediately.
    • It waits till it receives the first request.
    • Once the object is created the same object will be maintained till end of the application.
  3. By default it considers all the configured classes as singleton classes.
  4. So that the same object will be given to all requests which belongs to same class.
  5. We cannot change singleton scope for core container.
  6. provides the fundamental functionality of the Spring framework.
  7. BeanFactory, the heart of any Spring-based application.

Advanced container or ApplicationContext container

  1. It is advanced container.
  2. By default it supports early loading.
    • It means without receiving any request from client program immediately it will create object for every singleton scoped class.
    • When ever the container gets activated immediately it creates objects of all singleton classes.
  3. Has many advantages over core container.
ApplicationContext container is enhancement of bean factory container with some advantages.
Its features are as follows:
  1. Pre initialization of beans by default. [Early loading]. It means in our spring configuration file we may have any no. of bean tags. Objects will be created sequentially for each and every bean class as specified in the sequence of <bean> tags in xml file.
  2. Ability to read values of bean properties from properties file.
  3. supports Internationalization (I18n)
  4. Gives the ability to work with events & listeners.
  5. org.springframework.context.ApplicationContext interface is the sub interface of org.springframework.beans.factory.BeanFactory interface.
  6. Activating application context interface is nothing but creating object of a class that implements org.springframework.context.ApplicationContext interface.
  7. There are three regularly used implementation classes of application context interface. By creating object for any of these three classes we can activate ApplicationContext container.
  8. This container is available in JEE module.
  9. org.springframework.context.support.FileSystemXmlApplicationContext: It activates application context container by locating given spring configuration file in the specified path.
    Ex:
    FileSystemXmlApplicationContext ctx = new
      FileSystemXmlApplicationContext("c:\f1\spriong.cfg.xml")
    
  10. org.springframework.context.support.ClassPathXmlApplicationContext: It activates application context container by locating spring configuration file in the same working directory or from jar files added in the classpath.
    Ex:
    ClassPathXmlApplicationContext ctx = new
      ClassPathXmlApplicationContext("spring.cfg.xml");
    
  11. org.springframework.context.support.XmlWebApplicationContext: this class activates application context container by locating spring configuration file in deployment directory structure of web application by default in WEB-INF folder.
    Ex:
    XmlWebApplicationContext ctx = 
        new XmlWebApplicationContext("spring.cfg.xml");
    
  12. In real time applications we can find regularly working with Application Context container rather than working with Bean Factory container.
  13. Application context container can perform all modes of dependency injection like bean factory container.
  14. Application context container performs pre instantiation on all singleton scoped on spring bean classes of spring configuration file at the moment of application context container gets activated.
  15. Pre-instantiation means creating spring bean class objects immediately after the application context container activation.
  16. BeanFactory cannot perform this pre instantiation on spring bean classes.
  17. when we call factory.getBean(_) then bean factory container immediately creates the object and uses the same for further requests on same id-value.
  18. When we call ctx.getBean(_) then application context container gives access to bean id related spring bean class object which is created at pre-instantiation process.
  19. Application context container can perform pre-instantiation only on singleton scoped spring bean classes that are configured in spring configuration file.
  20. If we give scope value as prototype then object will not be created for bean at the time of pre-instantiation.
  21. If the object is not created at pre-instantiation then it will be created after receiving the call along with its dependent objects.
  22. If singleton scope bean class property has prototype scoped bean class object as dependent value then the application context container also creates prototype scoped spring bean class object during pre instantiation process along with singleton scope bean class object.
  23. It happens to satisfy dependency injection needs done on singleton scope bean class properties.

Initializing Spring Core Container & Accessing Spring Beans :

//Using BeanFactory to instantiate spring core container

BeanFactory beans= new XmlBeanFactory(
		new FileSystemResource("mybeans.xml"));
 
We are using XmlBeanFactory implementation for instantiating the spring container with 'mybeans.xml' file as configuration file.
 //Using ApplicationContext to instantiate spring core container
ApplicationContext context=
      new ClassPathXmlApplicationContext("mybeans.xml");
 
We are using ClassPathXmlApplicationContext implementation for instantiating the spring container with 'mybeans.xml' file as configuration file.
Example 1:
HelloService.java
 package com.core;

public class HelloService {
 String message;
 public HelloService(){
  message="msg from default Constructor";
 }
 
 public HelloService(String msg){
  message=msg;
 }
 
 public String getMessage(){
  return message;
 }
}//class 
mybeans.xml
<?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-2.5.xsd">
	
<bean id="helloService1" class="com.core.HelloService"/>

<bean id="helloService2" class="com.core.HelloService">
 <constructor-arg>
  <value>hello from configuration</value>
 </constructor-arg>
</bean>

</beans>
HelloServiceTestCase.java
package com.core;

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

public class HelloServiceTestCase {
public static void main(String[] args) {
	
 BeanFactory beans=
       new XmlBeanFactory(new FileSystemResource("mybeans.xml"));
 
 HelloService hello1=(HelloService)beans.getBean("helloService1");
 System.out.println(hello1.getMessage());
 
 HelloService hello2=(HelloService)beans.getBean("helloService2");
 System.out.println(hello2.getMessage()); 
}//main

}//class
output :
msg from default Constructor
hello from configuration

Types of Dependency Injection :

We have 2 types of dependency injection options
  1. Constructor Injection
  2. Setter Method Injection
Constructor Injection
Injecting the dependencies of an object through its constructor arguments

If the constructor is establishing the dependencies between objects, we call it as Constructor Injection.


constructor Injection example :
Employee.java
package com.core;

public class Employee {

private String no;
private String name;
private String address;

Employee(String no,String name,String address){
 this.no=no;
 this.name=name;
 this.address=address;
 
 System.out.println("We are in Parameter Constructor");
}

}
applicationContext.xml
<bean id="emp" class="com.core.Employee">
 <constructor-arg type="java.lang.String" index="0">
   <value type="java.lang.String">25</value>
 </constructor-arg>
  <constructor-arg type="java.lang.String" index="1">
   <value type="java.lang.String">Ashok</value>
 </constructor-arg>
  <constructor-arg type="java.lang.String" index="2">
   <value type="java.lang.String">HYD</value>
 </constructor-arg>
</bean>
  • The spring container find the constructors based on number of parameters.
  • When we configure constructor injection, we know need to supply index attribute, if we doesn't supply index attribute by default the tag is considered as parameter zero, 2nd tag is considered as parameter index '1' etc.,
  • If we don't specify type default spring uses the data types of spring bean.
  • Even though index and type attributes are optional its always recommended to use index and type attributes.
  • These resolve the conflict of overloaded constructors instead of using index attribute we can use name attribute to specify to which variable we are supplying the value.
<bean id="emp" class="com.core.Employee">
 <constructor-arg name="no" type="int" value="2"/>
 <constructor-arg name="name" type="String" value="Ashok"/>
 <constructor-arg name="address" type="String" value="HYD"/> 
</bean>
  • When ever mandatory properties are available , when the object is created we have to initialize them, in this scenario we use constructor injection.
  • Based on the user choice we want to initialize the properties in this scenario we use setter method injection.
Setter Method Injection

If the setter method is establishing the dependencies between objects, we call it as Setter Method Injection.

Requirement :
create a spring bean address with 3 properties and establish the dependencies and ask the spring container to create the object
spring bean :In spring, java beans are considered as spring-beans.

Address.java
package com.core;

public class Address {

private String street;
private String city;
private String state;

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 getState() {
	return state;
}
public void setState(String state) {
	this.state = state;
}

}//class
  • If we want spring container to create the object and establish the dependencies, we must configure spring configuration file.
  • Instead of manual configuration, we take a help of view(i.e., spring explorer)


applicationContext.xml
<?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-2.5.xsd">
	
<bean id="addr" class="com.core.Address" 
      abstract="false" lazy-init="default" autowire="default">

<property name="street">
 <value type="java.lang.String">Apet</value>
</property>
<property name="city">
 <value type="java.lang.String">HYD</value>
</property>
<property name="state">
 <value type="java.lang.String">IND</value>
</property>

</bean>

</beans> 
  • When we configure spring bean into spring bean configuration file we must specified spring type.
  • The spring type is based on the property data type.
    spring types : ref, idref, value, null, set, list, map, props
  • When we configure spring bean into spring bean configuration file, to reduce the spring bean configuration file Spring 3.0 has provided an option P-namespace.

    xmlns:p="http://www.springframework.org/schema/p"

    <bean id="addr" class="com.core.Address" 
          p:street="APet" p:city="HYD" p:state="IND" />
    
  • Spring container consider attributes as properties.
    If We doesn't to specify type attribute by default spring uses the property type of spring bean.
    To resolve the configuration is to spring bean configuration file instead of value tags, we can use value attribute.
    <bean id="addr" class="com.core.Address" >      
    
      <property name="city" value="Bangalore" />
      <property name="state" value="Karnataka" />
     
    </bean>
    
  • ClassPathResource can be used to read the context of resources which is available in side ClassPath of our ClassPath.
  • FileSystemResource can be used to read the content of resource which is available in our computer.
MyApp.java
package com.core;

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

public class MyApp {

public static void main(String[] args) {
 Resource resource=
    new ClassPathResource("com/core/applicationContext.xml");
 BeanFactory container=new XmlBeanFactory(resource);
 System.out.println("container : "+container);
 
 Object o=container.getBean("addr");
 Address a=(Address)o;
 System.out.println("Street : "+a.getStreet());
 System.out.println("City : "+a.getCity());
 System.out.println("State : "+a.getState());
}//main

}
Output :
container : org.springframework.beans.factory.xml.XmlBeanFactory@64883c: 
             defining beans [addr]; root of factory hierarchy
        
Street : Apet
City : HYD
State : IND
  • When we create a spring container object based on XmlBeanFactory immediately it is not creating spring bean object and establish the dependencies.
  • When ever we call a method getBean(), then only we create the object and perform dependency.

When we try to remove configuration file from classpath and try to run the program, we get an exception saying java.io.FileNotFoundException

When the spring container create the object, it has initialized with default values.

abstract attribute :
  • We can use an abstract attribute, if we don't want to allow any body to create an object by default abstract="false"
  • If we make as abstract="true", spring container can't create the object to the spring bean id.
  • specify abstract="true", we can not saying the spring bean class also abstract.
The following is an example of creating a spring container based on FileSystemResource :
package com.core;

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

public class MyApp {

public static void main(String[] args) {
 Resource resource=
    new FileSystemResource("D:/work/applicationContext.xml");
 BeanFactory container=new XmlBeanFactory(resource);
 System.out.println("container : "+container);
 
}//main

}
What is the purpose of getBean() method :
  • getBean() is used to ask the spring container and establish dependencies.
  • When ever we call getBean() method every time it is not creating spring bean object.

In the most of the projects we may use singleton design pattern (OR) We may create multiple objects we can control this based on scope.

  • When we create the spring container object based on the XmlBeanFactory until & unless we call getBean() it will not create spring bean object and establish the dependencies
     Object o=container.getBean("addr");
    
  • When the above code is executed, it will take the id and check whether the id is available, it will take the class name and create the object and establish the dependencies. Now the getBean() converts the object into super-class object.
  • If we call getBean() with an id, which is not available we will get an Exception org.springframework.beans.factory.NoSuchBeanDefinitionException.
  • Instead of using getBean() we can directly get the object by using our loaded method getBean()
    syntax :
     
    T  getBean(String name, class<T> required type)
     
    Address addr=container.getBean("addr",Address.class);
    
Every time when we call a getBean(), is it creating a new spring bean and establishing dependencies ?
  • getBean() behavior is based on the scope attribute in the spring bean configuration file.
  • If no scope attribute is specified by-default it uses scope="singleton" it will create the object only once and it will returns the same object every time, when we call getBean()
    Address addr1=container.getBean("addr",Address.class);
    Address addr2=container.getBean("addr",Address.class);
    
    System.out.println(addr1); 
    System.out.println(addr2);  //same hashcode
    

  • Core module we have to bean package & context package.
  • By using context package we can create IOC container.
  • By using context IOC package it takes care of I18N applications.
  • The context package contains an interface "ApplicationContext" (org.springframework.context)
  • This interface internally inherits the properties of "BeanFactory" interface
  • Any class which provide the implementation of ApplicationContext also can be called as spring container.
  • ClassPathXmlApplicationContext, FileSystemXmlApplicationContext provide the implementation of ApplicationContext.(org.springframework.context.support)

  • When ever we create spring container object based on ApplicationContext and if the scope="singleton" immediately spring container create the object and establish the dependencies.
  • When ever we configure spring bean into spring bean configuration file and scope="singleton", it will create the objects the order of object creation is top to bottom.
lazy-init attribute :
  • lazy-init attribute is used to specified when the spring container has to create spring bean object.
  • lazy-init attribute work only if scope="singleton".
  • spring container will not consider lazy-init if the scope value is prototype/request/session.
  • lazy-init="default" means lazy-init="false"
  • If lazy-init="false" and scope="singleton" whenever spring container creates the object immediately.
<bean name="addr" class="com.core.Address" 
            lazy-init="false" scope="singleton"/>
Requirement :
Implement dependency between an address object and employee object
Address.java
package com.core;

public class Address {

private String street;
private String city;
private String state;

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 getState() {
	return state;
}
public void setState(String state) {
	this.state = state;
}

}//class
Employee.java
package com.core;

public class Employee {
	
private int no;
private String name;
private Address address;

public int getNo() {
	return no;
}
public void setNo(int no) {
	this.no = no;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public Address getAddress() {
	return address;
}
public void setAddress(Address address) {
	this.address = address;
}

}
Employee spring bean dependent on Address spring bean.

We have to configure the above 2 spring beans into spring configuration file.

applicationContext.xml
<bean id="emp" class="com.core.Employee" >
 <property name="no" value="1"/>
 <property name="name" value="Ashok"/>
 <property name="address">
    <ref bean="addr"/>
 </property>
</bean>
	
<bean id="addr" class="com.core.Address" >
  <property name="street" value="Abc"/>
  <property name="city" value="Bangalore"/>
  <property name="state" value="Chennai"/>
</bean>

When we create a spring container object and call the getBean() method, it will create the Employee object as well as Address object.Because Employee is dependent on Address.

What is Wiring :
  • Connecting 2 different objects is called Wiring (OR) Establishing dependencies between the objects is called as Wiring.
  • By default spring uses manual wiring the meaning of it is, if we doesn't specify the dependencies spring container will not establish the dependencies.
auto-wire attribute :
By default auto-wire attribute take values
  • byName
  • byType
By default auto-wire="no" , the meaning of it is spring container is looking for manual wiring.
auto-wire="byName"

in this case the spring container automatically establish the wiring/dependencies, if the property name and bean id are same.

<bean id="emp" class="com.core.Employee" 
               lazy-init="true" autowire="byName">
 <property name="no" value="1"/>
 <property name="name" value="Ashok"/>
</bean>
	
<bean id="address" class="com.core.Address" lazy-init="true">
  <property name="street" value="Abc"/>
  <property name="city" value="Bangalore"/>
  <property name="state" value="Chennai"/>
</bean>
Note : If manual wiring is specify, auto-wire will not considered by spring container.
auto-wire="byType"

in this case the spring container check is there any beans are configured with that data type , if it is configured it will establish the dependency.

<bean id="emp" class="com.core.Employee" 
               lazy-init="true" autowire="byType">
 <property name="no" value="1"/>
 <property name="name" value="Ashok"/>
</bean>
	
<bean id="addr" class="com.core.Address" lazy-init="true">
  <property name="street" value="Abc"/>
  <property name="city" value="Bangalore"/>
  <property name="state" value="Chennai"/>
</bean>
The dis-advantage of "byType" is if multiple spring beans are configured for the same type it throws an Exception "UnsatisfiedLinkError".
While we are configuring spring bean into spring bean configuration file we use id or name.
Difference between id and name attributes :
  • id attribute doesn't allow to take special character as input.
    where as name attribute allow as to take special character.
    <bean id="/addr" />   //invalid
    <bean name="/addr" />  //valid
    
  • By using name attribute to a single name (or) two names to a bean.
    <bean name="addr1, addr2" class="com.Address" scope="prototype" />
    
    Note : We can use space also as a character for the names in bean type.
    <bean name="addr1 addr2" />
    
  • To the spring beans we can assign the alias names also.
    The advantage of alias names is different people can use sane bean with different names.
    <beans>
    <bean id="addr1" class="com.core.Address" scope="singleton"/>
    <alias name="addr1" alias="addr2"/>
    </beans>
    
  • We can ask the spring container creates the object based on alias names also.
    container.getBean("addr2");
    

Requirement :
In the spring based project we always use multiple spring bean configuration files because of the maintanance of the project becomes easy

configure Employee bean into applicationContext.xml and Address bean into customerContext.xml

We have to supply both these beans parameter to container object, we can use any of the following two approaches

Approach 1:
ApplicationContext container=new ClassPathXmlApplicationContext(
       new String[]{"com/core/applicationContext.xml",
                         "com/core/customerContext.xml"});

 container.getBean("addr");
 container.getBean("emp");
Approach 2:
ApplicationContext container=new ClassPathXmlApplicationContext(
		              "com/core/applicationContext.xml",
		                      "com/core/customerContext.xml");
 container.getBean("addr");
 container.getBean("emp");

In the above configuration we are hard coding the configuration file names instead of hard coding we use wild character search

ApplicationContext container=
   new ClassPathXmlApplicationContext("com/core/*.xml");
                           //not working BeanFactory

 container.getBean("addr");
 container.getBean("emp");

We can use an import tag to import one spring bean into another spring bean.

applicationContext.xml
<beans>
 <import resource="customerContext.xml"/>	
</beans>

ref tag :

ref tag takes multiple attributes they are : bean, parent, local.

<ref bean="addr"/>
When we specified <ref bean="addr"/> spring container checks whether the reference is available in current configuration file,
if not available it checks in all the imported configuration file and create the object.
<ref local="addr"/>
When we specified <ref local="addr"/> spring container always checks in the current configuration file only.
If it is not available in the current configuration file spring container throws an exception.
<ref parent="addr"/>
When we specified <ref parent="addr"/> spring container checks for reference in parent spring container.

In spring we can create multiple spring containers, we can make some container are parent containers, some containers are child containers.

The advantage of using child containers is we can access the beans from child containers as well as parent containers.

The following configuration of parent and child containers

ApplicationContext pContainer=new ClassPathXmlApplicationContext(
		                 "com/core/applicationContext.xml");

ApplicationContext cContainer=new ClassPathXmlApplicationContext(
	new String[]{"com/core/customerContext.xml"},pContainer);

 cContainer.getBean("addr");
 cContainer.getBean("emp");
Developing spring based application by using manual procedure :
  1. To develop the manual procedure we have to set the class path to following jar files :
    1. beans.jar
    2. core.jar
    3. context.jar
    4. context-support.jar
    5. expression.jar
    6. asm.jar
    As spring internally uses log4j we have to set the classpath to "common-logging.jar"
  2. Develop spring bean configuration file.(EX: applicationContext.xml)
  3. Develop spring bean and configure in spring configuration file.
  4. Develop the java application to call the spring container.

We have to supply the values to properties according to the datatypes of the property.

Data Types of property :

We have to classified data types into 5 categories
  1. String type
  2. Reference type
  3. Primitive type
  4. Arrays
  5. Collections
null :
We use this tag to supply null value to a property
<property name="name">
  <null/>
</property>
According to the above configuration name property hold the "null" value.
primitive :
For primitive datatypes we use a tag "value".
We can specify the data type by using "type" attribute.
 <property name="no">
  <value type="int">10</value>
 </property>
 
 <property name="male">
  <value type="boolean">true</value>
 </property>
 
 <property name="salary">
  <value type="double">1000.00</value>
 </property>
Arrays :
If we have any property whose type is an array to supply the value, we use a tag value with comma(,) separator. Employee.java
package com.core;

public class Employee {

String[] parents;

public String[] getParents() {
	return parents;
}
public void setParents(String[] parents) {
	this.parents = parents;
}

}
applicationContext.java
<bean id="emp" class="com.core.Employee">
 <property name="parents">
  <value>father,mother</value>
 </property> 
</bean>
Collections :
ArrayList :
To supply a value to arraylist property we use a tag "list"

Employee.java
package com.core;
import java.util.ArrayList;

public class Employee {

ArrayList projects;
public ArrayList getProjects() {
	return projects;
}
public void setProjects(ArrayList projects){
	this.projects = projects;
}

}
applicationContext.xml
<bean id="emp" class="com.core.Employee">
 <property name="projects">
  <list>
   <value>BMS project</value>
   <value>ZING project</value>
  </list>
 </property> 
</bean>
MyApp.java
package com.core;

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

public class MyApp {

public static void main(String[] args) {
 
ApplicationContext container=new ClassPathXmlApplicationContext(
		                        "com/core/applicationContext.xml");

 Employee e=(Employee)container.getBean("emp");
 System.out.println(e.getProjects());
 
}//main

}

output :

[BMS project, ZING project]

Ex 2 :

We are created a project bean, the project bean is responsible for holding the project information.

Project.java
package com.core;

public class Project {
 String projectName;
 String customerName;
  
public String getProjectName() {
	return projectName;
}
public void setProjectName(String projectName) {
	this.projectName = projectName;
}
public String getCustomerName() {
	return customerName;
}
public void setCustomerName(String customerName) {
	this.customerName = customerName;
}
 
}

An Employee can have multiple projects to store the project information
We are using the following bean with ArrayList property.

Employee.java

package com.core;
import java.util.ArrayList;

public class Employee {

ArrayList projects;
public ArrayList getProjects() {
	return projects;
}
public void setProjects(ArrayList projects){
	this.projects = projects;
}

}
To supply ArrayList values with object, we use following tags
<bean name="bms" class="com.core.Project">
 <property name="projectName" value="BMS project"/>
 <property name="customerName" value="Ashok"/> 
</bean>
<bean name="zing" class="com.core.Project">
 <property name="projectName" value="Zing project"/>
 <property name="customerName" value="Arun"/> 
</bean>

<bean id="emp" class="com.core.Employee">
 <property name="projects">
  <list>
    <ref bean="bms"/>
    <ref bean="zing"/>
  </list>
 </property> 
</bean>
Set :
Employee.java
package com.core;
import java.util.HashSet;

public class Employee {

HashSet projects;
public HashSet getProjects() {
	return projects;
}
public void setProjects(HashSet projects) {
	this.projects = projects;
}

}
To configure setProperty to use set tag as shown below

applicationContext.xml

<bean id="emp" class="com.core.Employee">
 <property name="projects">
  <set>
   <value>LIC</value>
   <value>KSRTC</value>
  </set>
 </property> 
</bean>
Map :
Employee.java
package com.core;
import java.util.HashMap;

public class Employee {

HashMap projects;
public HashMap getProjects() {
	return projects;
}
public void setProjects(HashMap projects) {
	this.projects = projects;
}

}

The following configuration for HashMap

<bean id="emp" class="com.core.Employee">
 <property name="projects">
  <map>
   <entry key="p1" value="BMS project"/>
   <entry key="p2" value="Zing project"/>
  </map>
 </property> 
</bean>
Props :
Employee.java
package com.core;
import java.util.Properties;

public class Employee {

Properties projects;
public Properties getProjects() {
	return projects;
}
public void setProjects(Properties projects) {
	this.projects = projects;
}

}

applicationContext.xml (spring configuration file)

<bean id="emp" class="com.core.Employee">
 <property name="projects">
  <props>
   <prop key="p1">BMS project</prop>
   <prop key="p2">Zing project</prop>
  </props>
 </property> 
</bean>

Getting the data from spring bean configuration file and storing the data into object is called "Data binding process"
When the data binding process is happening we get "Bind Exception".

We would like to create a spring bean Student with sno, name, fatherName, motherName properties

Student.java

package com.core;

public class Student {
	
int no;
String name;
String fatherName;
String motherName;

public int getNo() {
	return no;
}
public void setNo(int no) {
	this.no = no;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}
public String getFatherName() {
	return fatherName;
}
public void setFatherName(String fatherName) {
	this.fatherName = fatherName;
}
public String getMotherName() {
	return motherName;
}
public void setMotherName(String motherName) {
	this.motherName = motherName;
}

}
When we want to use above spring bean to configure into 2 students properties like fatherName, motherName are getting related.

To resolve this problem we have configured the spring bean for configuring fatherName & motherName in one place declared the class as abstract.

Parent.java
package com.core;

public abstract class Parent {
 String fatherName;
 String motherName;
 
public String getFatherName() {
	return fatherName;
}
public void setFatherName(String fatherName) {
	this.fatherName = fatherName;
}
public String getMotherName() {
	return motherName;
}
public void setMotherName(String motherName) {
	this.motherName = motherName;
}

}
Student.java
package com.core;

public class Student extends Parent{
	
int no;
String name;

public int getNo() {
	return no;
}
public void setNo(int no) {
	this.no = no;
}
public String getName() {
	return name;
}
public void setName(String name) {
	this.name = name;
}

}
configuration file :
<bean id="parents" class="com.core.Parent" abstract="true">
 <property name="fatherName" value="abc"/>
 <property name="motherName" value="xyz"/> 
</bean>

<bean id="students" class="com.core.Student" parent="parents">
 <property name="no" value="1"/>
 <property name="name" value="SaiCharan"/>
</bean>
Java application :
package com.core;

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

public class MyApp {

public static void main(String[] args) {
 
ApplicationContext container=new ClassPathXmlApplicationContext(
		                  "com/core/applicationContext.xml");

Student s=(Student)container.getBean("students");
 System.out.println(s.getNo());
 System.out.println(s.getMotherName()); 
}//main

}
The advantage of above approach is we can inherit the properties of abstract bean and use it.

Dependency Injection Example :

EmployeeServices.java
package com.core;

public interface EmployeeServices {
 public boolean incrementSalary(int eno,double amount);
}
EmployeeServicesImpl.java
package com.core;

public class EmployeeServicesImpl implements EmployeeServices{
private	EmployeeDao employeeDao;

public void setEmployeeDao(EmployeeDao dao){
	employeeDao=dao;
}

 public boolean incrementSalary(int eno,double amount){
	 double sal=employeeDao.getSal(eno);
	 sal+=amount;
	 employeeDao.setSal(eno,sal);
	 System.out.println("salary :"+ sal);
	 
	 return true;
  }
}
EmployeeDao.java
package com.core;

public interface EmployeeDao {
 
void setSal(int eno,double amount);
double getSal(int eno); 
}
EmployeeDaoImpl.java
package com.core;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.DataSource;

public class EmployeeDaoImpl implements EmployeeDao{
 
private DataSource dataSource;
public EmployeeDaoImpl(DataSource ds) {
	dataSource=ds;
}
private Connection con;
public void setSal(int eno,double sal){
 try{
	 con=dataSource.getConnection();
	 PreparedStatement pstmt=
	       con.prepareStatement("update emp set sal=? where eno=?");
	 pstmt.setDouble(1, sal);
	 pstmt.setInt(2,eno);
	 int count=pstmt.executeUpdate();
	 System.out.println("update records :" +count);	 
 }
 catch(Exception e){
	 e.printStackTrace();
 }
 finally{
	try {
	 con.close();
	} catch (Exception e) {
		e.printStackTrace();
	}
 }//finally
	
}//setSal
public double getSal(int eno){
 try{
  con=dataSource.getConnection();
  PreparedStatement pstmt=
           con.prepareStatement("select sal from emp where eno=?");
  pstmt.setInt(1,eno);
  ResultSet rs=pstmt.executeQuery();
	if(rs.next())
	 return rs.getDouble(1);
	 throw new RuntimeException("Employee not found");
	 }//try
  catch(Exception e){
	e.printStackTrace();
	throw new RuntimeException();
  }
 finally{
	try {
	 con.close();
	} catch (SQLException e) {
		e.printStackTrace();
	}
 }//finally
} 
 
}
mybeans.xml
<?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-2.5.xsd">
	
<bean id="empservices" class="com.core.EmployeeServicesImpl">
 <property name="employeeDao">
    <ref local="dao"/>
 </property>
</bean>

<bean id="dao" class="com.core.EmployeeDaoImpl">
 <constructor-arg>
   <ref local="ds"/>
 </constructor-arg>
</bean>

<bean id="ds" class="org.apache.commons.dbcp.BasicDataSource">
 <property name="driverClassName">
  <value>oracle.jdbc.driver.OracleDriver</value>
 </property>
 <property name="url">
  <value>jdbc:oracle:thin:@localhost:1521:xe</value>
 </property>
 <property name="username">
   <value>system</value>
 </property>
 <property name="password">
  <value>tiger</value>
 </property>
</bean>

</beans>
EmployeeServicesTestCase.java
package com.core;

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

public class EmployeeServicesTestCase {
public static void main(String[] args) {
	
 BeanFactory beans=
     new XmlBeanFactory(new FileSystemResource("mybeans.xml"));
 EmployeeServices empservices=
            (EmployeeServices)beans.getBean("empservices");
 empservices.incrementSalary(Integer.parseInt(args[0]), 1000d);
}//main

}//class

Configuring Beans :

  • The Spring Core Container supports the bean configurations for different types of instantiations.
  • This is one of the advantage of spring framework allowing us to configure any existing java class to be instantiated and managed by the spring container.
  • Spring even supports the configuration of a static inner class for instantiation.
Spring supports 3 types of instantiations :
  1. Using constructor
  2. Static factory method
  3. Non-static factory method
Instantiating Bean using Constructor :
<!--instantiating bean with no argument constructor-->
<bean id="bean1" class="MyBeanClass1"/>

<!--instantiating bean with one String argument constructor-->
<bean id="bean2" class="MyBeanClass2">
 <constructor-arg type="java.lang.String">
   <value>Hello</value>
 </constructor-arg>
</bean>

<!--instantiating bean with two argument constructor-->
<bean id="bean3" class="MyBeanClass3">
 <constructor-arg index="1">
  <value>Hello</value>
 </constructor-arg>
 
 <constructor-arg index="0">
  <ref local="mybean"/>
 </constructor-arg>
</bean>
Instantiating Bean using Static factory method :
syntax :
<bean id="mybean" class="com.core.MyFactoryBean" 
                   factory-method="getInstance"/>
<bean id="con" class="java.sql.DriverManager" 
                               factory-method="getConnection">
<constructor-arg>
  <value>jdbc:oracle:thin:@localhost:1521:xe</value>
</constructor-arg>
<constructor-arg>
  <value>scott</value>
</constructor-arg>
<constructor-arg>
  <value>tiger</value>
</constructor-arg>

<property name="autoCommit">
 <value type="boolean">false</value>
</property>
</bean>
Instantiating Bean using Non-static factory method :
<bean id="bean1" class="com.core.MyFactoryBean"/>

<bean id="bean2" factory-bean="bean1" 
                 factory-method="getConnection"/>

Bean Scopes and LifeCycle

Scopes Description
singleton
  • This is default scope.
  • A bean defination configured with this scope is instantiated only once per container instance.
  • And all the requests for this bean or references created for this bean in the context will be given with the single object reference.
prototype
  • A bean defination configured with this scope is instantiated every time it is requested or referenced.
request
  • This scope is applicable only when using a web aware spring ApplicationContext.
  • A bean defination configured with this scope is instantiated for each HTTP request.
session
  • This scope is applicable only when using a web aware spring ApplicationContext.
  • A bean defination configured with this scope is instantiated for each HTTP session.
  • That is, the bean scoped with a session is shared between all the session's requests.
global session
  • This scope is applicable only when using a web aware spring ApplicationContext.
  • A bean defination configured with this scope is same as session scope.
  • Beans defind as the global session scope are scoped to the lifetime of the global portlet session.
Initialization :
  • To listen for the initialization lifecycle event the bean can implement org.springframework.beans.factory.InitializingBean interface.
  • This interface declares only one method afterPropertiesSet()
<bean id="mybean" class="com.core.BeanLifeCycle" 
                       init-method="initialize"/>
BeanLifeCycle.java
package com.core;

import org.springframework.beans.factory.InitializingBean;

public class BeanLifeCycle implements InitializingBean{

public BeanLifeCycle(){
 //invoke before the bean properties are set
//can perform initializations, but bean properties are not available
}
public void afterPropertiesSet()throws Exception{
 //invoke after the bean properties are set successfully
//can perform initializations, even using the bean properties 
}

}//class
Spring allows us to configure the default initialization method for all the beans configured in an XML configuration file.
<beans default-init-method="initialize">
 <bean id="mybean1" class="com.core.BeanLifeCycle1"/>
 <bean id="mybean2" class="com.core.BeanLifeCycle2"/>

 <bean id="mybean3" class="com.core.BeanLifeCycle3" 
                                     init-method="init"/>
</beans>
Destruction :
  • To listen for the destruction lifecycle event the bean can implement org.springframework.beans.factory.DisposableBean interface.
  • This interface declares only one method destroy()
<bean id="mybean" class="com.core.BeanLifeCycle" 
                            destroy-method="close"/>
BeanLifeCycle.java
package com.core;

import org.springframework.beans.factory.DisposableBean;

public class BeanLifeCycle implements DisposableBean{

public void destroy() throws Exception {
 //invoked just before the bean is put out of service
//can perform finalizations
}

}//class
Spring allows us to configure the default destruction method for all the beans configured in an XML configuration file.
 <beans default-destroy-method="close">
  <bean id="mybean1" class="com.core.BeanLifeCycle1"/>
  <bean id="mybean2" class="com.core.BeanLifeCycle2"/>
  <bean id="mybean3" class="com.core.BeanLifeCycle3" 
                               destroy-method="destroy"/>
 </beans>
 

Method Injection

LookUp Method Injection :
BusinessObject1.java
package com.core;

public abstract class BusinessObject1 {
	
public void service(){
 BusinessObject2 bo2=getBusinessObject2();		
}

public abstract BusinessObject2 getBusinessObject2();
}
mybeans.xml
<bean id="bean1" class="com.core.BusinessObject1" scope="singleton">
 <lookup-method name="getBusinessObject2" bean="businessObject2"/>
</bean>

<bean id="businessObject2" class="com.core.BusinessObject2" 
                                              scope="prototype"/>

I18N applications in core :

To deal with I18N applications spring guys are provided an interface org.springframework.context.MessageSource

This interface contains the methods which are used to deal with I18N applications.

The following UML diagram shows the important methods of interface
MessageSource
getMessage(key, arguments, locale)

'ApplicationContext' interface inherits the properties of 'MessageSource' because of this reason when ever we create spring container object , it is taking care of I18N applications as part of org.springframework.context.support package.

The following classes provides implementation of MessageSource inteface
  • ResourceBundleMessageSource
  • ReloadableResourceBundleMessageSource
  • StaticMessageSource

By using above classes we provide the information about our property files to spring container.

Procedure to use I18N applications:
  1. create the property files based on the number of languages we would like to support.
    (src folder)
    one = one in English
    two = two in English
    three = three in English
    

    resOne_en_US.properties



    one = one in French
    two = two in French
    three = three in French
    

    resOne_fr_CA.properties


  2. configure ResourceBundleMessageSource in spring bean configuration file.
    <bean id="messageSource" class=
      "org.springframework.context.support.ResourceBundleMessageSource">
      
     <property name="basename" value="resOne"/>
    </bean>
    
  3. create a spring container object and call a method getMessage()
    package com.core;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.*;
    
    
    public class MyApp {
    
    public static void main(String[] args) {
     
    ApplicationContext container=new ClassPathXmlApplicationContext(
    		              "com/core/applicationContext.xml");
    
     System.out.println(container.getMessage("one", null, null));
    }//main
    
    }
    
  4. If we are retrieving a key which is not available we get an exception NoSuchMessageException.
  5. As part of spring property file we can use configurable messages for example
    one = one in English {0} and {1}
    

    resOne_en_US.properties

  6. To supply the values to above parameters we use the following syntax :
    package com.core;
    import java.util.Locale;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.*;
    
    
    public class MyApp {
    
    public static void main(String[] args) {
     
    ApplicationContext container=new ClassPathXmlApplicationContext(
                           "com/core/applicationContext.xml");
    
     System.out.println(container.getMessage("one", 
    		  new String[]{"valueOne", "valueTwo"}, 
    		                 Locale.getDefault()));
    }//main
    
    }
    

    MyApp.java

Using multiple bundles in spring :

To use multiple bundles we have to use a property basenames by using a comma(,) separated values of basenames.

<bean id="messageSource" class=
  "org.springframework.context.support.ResourceBundleMessageSource">
  
 <property name="basenames" value="resOne,resTwo"/>
</bean>


BACK