Spring Core Container Module




Spring Core Container Module

The core container module provides the fundamental functionalities of the spring framework. In this module primary component is the BeanFactory, its sub interface ApplicationContext and its subclasses.
These classes are called as Spring container classes.
Their primary goal of spring container is:
·        Working as IoC container
·        Resource management service
·        Lifecycle service
·        Additional services AOP container provides (Logging, Security, TXs, Testing, Fail-over handling)
The two container super interfaces are:
·        BeanFactory
·        ApplicationContext
BeanFactory container is used to lazy loads bean instances. In this container also bean instances are singleton by default but created when getBean() method is called.
BeanFactory interface is having one sub class called
·        XmlBeanFactory (This class loads spring config file using filename)
o   BeanFactory f=new XmlBeanFactory(new FileInputStream(“beans.xml”));
o   BeanFactory f=new XmlBeanFactory(new FileSytsemResource(“beans.xml”));
ApplicationContext container is used to eager load bean instances. In this container also bean instances are singleton by default but created at the time of container startup. It is more useful in when spring is used in web and other j2ee applications.
ApplicationContext interface is having 3 sub classes they are:
·        FileSystemXmlApplicationContext (This class loads spring file from file system)
·        ClassPathXmlApplicationContext (This class loads spring file from classpath)
·        XmlWebApplicationContext (This class loads spring file in spring web & web mvc applications)
The structure of spring config file is
<beans> beans tag is the root tag of spring config file
<beans>
 <import resource=””>
<alias name=”” alias=””>
<bean id=”” class=”” lazy-init=”” scope=”” init-method=”” destroy-method=””>
               <!-- used for constructor injection -->
               <constructor-arg index=”” type=”” ref=”” value=”” >
                              <ref bean=”” />
<value</value>
<list>
               <value></value>
               <value></value>
               <ref bean=””/>
</list>
<set>
 <value></value>
               <ref bean=””/>
</set>
<map>
               <entry key=”key1”>
                              <value></value>
</entry>
               <entry key=”key2”>
                              <ref bean=””/>
</entry>
</map>
<props>
               <prop key=”key1”>value1</prop>
               <prop key=”key2”>ref2</prop>
</props>
               </constructor-arg>

<!-- property injection also takes the same number of sub tags as constructor-arg takes  -->
               <property name=”” type=”” value=”” ref=””>
               </property>

</bean>
</beans>

We will learn more details of these tags in next coming sections.
Bean’s lifecycle in BeanFactory
·        The container finds bean configuration in and instantiates bean.
·        Using dependency injection spring populates all the properties as specified in spring xml file
·        Bean implements BeanAware interface, the factory calls setBeanName() passing bean’s ID
·        If Bean implements BeanFactoryAware interface the factory calls setBeanFactory(), passing instance of itself
·        If there are any BeanPostProcessors associated with the bean, their PostProcessBeforeInitialization() methods are called
·        If an init-method is specified for the bean they will be called
·        Finally it there are any BeanPostProcessors associated with the bean, their postProcessAfterInitialization() methods are called

At this time bean is ready to use in application. Bean instance remains in spring container when container shutdowns destroy-method specified in spring xml file is called or DisposableBean interface destroy() method is called.

Bean’s lifecycle in ApplicationContext
The only difference between BeanFactory and ApplicationContext is if bean implements ApplicationContextAware interface the setApplicationContext() method is called.

Singleton Vs Prototype Vs Request Vs Session
·        Singleton instances are created usually at the time of container startup in case of ApplicationContext and bean instances are created when getBean() method is called in case of BeanFactory.
·        Singleton instance is a single instance through spring container.
·        Prototype instances are created as many times as we request getBean() method in our client program.
·        Prototype instances are not created at the time of container startup because we want to call getBean() method to get the bean instance, they are created on-demand.
·        Request scope bean instance must be used in when using Spring web application framework. Their scope is the same bean instance is returned throughout the conversation.
·        Session scope instances are per session scope. Whether you request single call HTML call or multiple calls on web application if you request from the same browser their instances are same.

Initialization and Destruction
When beans are instantiated and injections takes place it is necessary to call init() method to further initialize some more variables such as if we obtain DataSource it is necessary to call getConnection () method to get Connection object. Such initializations takes place in init() method.

destroy() methods are called during container shutdown. In this method we will close all DB objects.
Constructor and Setter Injection
Favor on Constructor Injection
·        When dependent objects are mandatory then constructor injection is suitable.
·        When dependent objects are optional then setter injection is suitable.

·        If dependent objects are passed through constructor less amount of code consumes
·        If dependent objects are passed through setter injection more amount of code occupies in both bean and spring config file.

·        If any dependent objects are passed through constructor injection we need not have to write setter method for the property hence the property becomes passed into bean becomes immutable / cannot be modified in future in the bean.
Disfavor on Constructor Injection
·        Constructor’s parameters list increases, looks very length. Declaring such constructors in the bean is cumbersome/awkward.
·        If there are several ways to create object of a bean then many constructors we need to write. If different constructors are written with different signatures and with more number of parameters then defining constructors itself takes lot of time, using them in spring config file is also tough.
·        If constructor takes two parameters of the same type it may be difficult to determine what each parameter is.

Bean Wiring
·        Byname Attempts to find bean in the container whose name (or id) is the same as name of the property.
·        byType Attempts to find single bean in the container whose type is matched with the property. type looking for injection.
·        constructor Tries to match one or more beans in the container with the parameters of one of the constructors of the bean being matched.
·        Autodetect – Attempts to auto-wire by constructor first and then using byType.
Configuring external file in spring
Since every standalone – J2EE application are in need of using DB connection object preferably retrieved from the DataSource / Connection Pool object. Because connection obtained from the connection pool are efficient.
Hence configuring DataSource is essential in J2EE frameworks like Struts, JSF, Spring, JPA, Hibernate etc.
But while configuring DataSource even if we pass driver information such as driver class name, url, username and password is non-recommendable.
Hence passing driver properties from an external jdbc.properties file is the most preferred mean.
Hence write one jdbc.properties file
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:521:XE
jdbc.username=username
jdbc.password=password
Configure DataSource in spring config file like below:
<bean id=”propertyCongfigurer” class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>
               <property name=”location”>
                              <value>jdbc.properties</value>
                              <value>security.properties</value>
                              <value>application.properties</value>
                              <value>build.properties</value>
                              <value>log4j.properties</value>
               </property>
</bean>
<bean id=”ds” class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
               <property name=”driverClassName”>
                              <value>{jdbc.driver}</value>
               </property>
               <property name=”url” value=”{jdbc.url}”/>
               <property name=”username” value=”{jdbc.username}”/>
               <property name=”password” value=”{jdbc.password}”/>
</bean>
Resolving text messages
To implement Internationalization in Spring, we need to write following properties files:
training.properties
course =Course
training =Training
student =Student
computer =Computer {0}
training_en_US.properties
course =Course
training =Training
student =Student
computer =Computer {0}
training_fr_FR.properties
course = bien sûr
training = la formation
student = étudiants
computer = informatique {0}
training_es_ES.properties
course = curso
training = formación
student = estudiante
computer = computadora {0}
Configure following tag in spring config file:
<bean id=”messgeSource” class=”org.springframework.context.support.ResourceBundleMessageSource”>
               <property name=”basename” value=”training”>
</bean>
Writing following lines in Spring Client program/anywhere in the bean class:
Locale locale= new Locale(“en”);
String text=context.getMessage(“computer”, new Integer(1), locale);
Write the following code in JSP in case of spring web MVC framework:
<spring:message code=”computer” arguments=”1”/>
Listening for events
Listeners concept is common in many Java & J2EE traditional and modern frameworks. Even spring is also supporting it. Spring ApplicationContext container can publish a handful of events that tell interested listeners what’s going on. These events are all sub classes of org.springframework.context.ApplicationContextEvent.
Three such application events are:
·        ContextClosedEvent – Published when application context is closed.
·        ContextRefreshedEvent – Published when the application context is initialized or refreshed.
·        RequestHandledEvent – Published within the web application context when a request is handled.
Publishing events
public class Course {
               private int courseId;
               private String courseName;
               private String faculty;
               private String courseContent;
}

public class BatchFullListener implements ApplicationListener {

               public BathcFullListener() {
               ApplicationContext ac=new FileSystemXmlApplicationContext(“ApplicationContext.xml”);
               Course c=new Course(1, “Spring 2.5”,, “Surya”, “7 modules”);
               context.publishEvent(new BatchFullEvent(this, course));
}

               public void onApplicationEvent(ApplicationEvent ae) {
                              Course course=ae.getCourse();
                              System.out.println(course);
}
}

public class BatchFullEvent extends ApplicationEvent {
               private Course course;
public BatchFullEvent(Object source, Course course) {
super(source);
this.course=course;
}
public Course getCourse() {
               return course;
}
}
In spring config file
<bean id=”refreshListener” class=”BatchFullListener”/>
Making Bean’s Aware (Knowing who you are, Where you live)
Developing first application in Spring
ENV.cmd
SET CLASSPATH=%CLASSPATH%;D:\spring-framework-2.5.4\dist\spring.jar;D:\spring-framework-2.5.4\lib\jakarta-commons\commons-logging.jar

// Hello.java
import org.springframework.beans.factory.*;
public class Hello implements DisposableBean
{
  /* dependent object, we want to pass string thru constructor/setter method */
  String name;

  // for constructor injection
  public Hello(String name) {
    this.name=name;
    System.out.println("Hello(name) constructor called ");
  }

  // for setter injection
  // one no parameter constructor is required
  public Hello(){
    System.out.println("Hello() constructor called ");
  }
  // one setter method to receive String value
  public void setName(String n) {
   name=n;
    System.out.println("setName() method called ");
  }

  // two lifecycle methods
  public void init() {
    System.out.println("init() method");
  }
  public void destroy() {
    System.out.println("destroy() method");
  }

  // one business logic method
  public void sayHello() {
    System.out.println("Hello "+name);
  }
}

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"
                              xmlns:context="http://www.springframework.org/schema/context"
                              xmlns:tx="http://www.springframework.org/schema/tx"
                              xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                                                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                                                            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<bean id="h1" class="Hello" init-method="init">
 <constructor-arg value="Yogesh"/>
</bean>

<bean id="h2" class="Hello" init-method="init">
 <property name="name" value="NET"/>
</bean>

</beans>

applicationContext1.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"
                              xmlns:context="http://www.springframework.org/schema/context"
                              xmlns:tx="http://www.springframework.org/schema/tx"
                              xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                                                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
                                                            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<bean id="h1" class="Hello" scope="singleton" init-method="init" destroy-method="destroy">
 <constructor-arg value="Yogesh"/>
</bean>

<bean id="h2" class="Hello" scope="prototype" init-method="init" destroy-method="destroy">
 <property name="name" value="NET"/>
</bean>

</beans>

// Client.java
import org.springframework.beans.factory.*; // interface
import org.springframework.beans.factory.xml.*; // impl class
import org.springframework.core.io.*; // InputStreamResource
import java.io.*; // FileInputStream
import org.springframework.context.*; // ApplicationContext
import org.springframework.context.support.*; // FileSystemXmlApplicationContext
public class Client {
  public static void main(String rags[]) throws Exception   {
    BeanFactory f=new XmlBeanFactory(new FileSystemResource("applicationContext.xml"));
    Hello h1=(Hello)f.getBean("h1");
    h1.sayHello();
    h1=(Hello)f.getBean("h1");
    h1.sayHello();
    Hello h2=(Hello)f.getBean("h2");
    h2.sayHello();
    h2=(Hello)f.getBean("h2");
    h2.sayHello();
  }
}

Client1.java
import org.springframework.beans.factory.*; // interface
import org.springframework.beans.factory.xml.*; // impl class
import org.springframework.core.io.*; // InputStreamResource
import java.io.*; // FileInputStream
import org.springframework.context.*; // ApplicationContext
import org.springframework.context.support.*; // FileSystemXmlApplicationContext
public class Client {
  public static void main(String rags[]) throws Exception   {
    ApplicationContext f=new FileSystemXmlApplicationContext("applicationContext1.xml");
    Hello h1=(Hello)f.getBean("h1");
    h1.sayHello();
    h1=(Hello)f.getBean("h1");
    h1.sayHello();
    Hello h2=(Hello)f.getBean("h2");
    h2.sayHello();
    h2=(Hello)f.getBean("h2");
    h2.sayHello();
  }
}
Important points:
·        If container is BeanFactory beans are loaded and instantiated on-demand/lazy loading. That means during getBean() method call bean instances are created. In BeanFactory all beans are singleton by default.
·        If container is ApplicationContext then beans are instantiated at the time of container start-up.
·        Even in case of ApplicationContext also singleton instances are only instantiated at the time of container start-up. If we specify prototype one bean instance is created at the time of container startup. But remaining bean instances are created when we call getBean() method.
·        During h1 instantiation only constructor injection takes place that means String "Yogesh" is passed as argument into constructor, after that init() is invoked, then bean instance is given to Client.
·        During h2 instantiation first object is created using no argument constructor, then String "NET" is passed as argument, followed by init() method is called and then bean instance is given to Client.
·        In case of singleton beans spring container maintains only one copy of bean instance throughout the container, though we call getBean() method for any number of times the same instance is given.
·        In case of prototype as many times as we call getBean() method those many bean instances are created.

3 comments:

  1. thanks for the useful information please keep posting
    http://thecafetechno.com/spring/

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete