Spring core
Javed Mulla
(Immediate Joiner, Valid Work Visa for UK)Senior Software Engineer at Consors Finanz BNP Paribas
IOC is heart of Spring framework. We are divided spring application into three logical parts. 1> classes or beans
2> IOC which act as glue in between beans and factories
3> Instantiation of container.
Beans: Beans are just POJO classes.
Beans are created such a way that it remove tight coupling using DI.
Using DI is best for testing.
Beans are create two ways : 1) Constructor Injection
2) Setter Injection
IOC : used to manage life cycle of beans
enforce to programme create beans by DI
define scope of beans.
assemble module using different beans
Initialization of IOC : initialize IOC using either beanfactory or applicationcontext.
The IoC container is responsible to instantiate, configure and assemble the objects. The IoC container gets informations from the XML file and works accordingly. The main tasks performed by IoC container are:
- to instantiate the application class
- to configure the object
- to assemble the dependencies between the objects
There are two types of IoC containers. They are:
- BeanFactory
- ApplicationContext
Difference between BeanFactory and the ApplicationContext
The BeanFactory and the ApplicationContext interfaces acts as the IoC container. The ApplicationContext interface is built on top of the BeanFactory interface. It adds some extra functionality than BeanFactory such as simple integration with Spring's AOP, message resource handling (for I18N), event propagation, application layer specific context (e.g. WebApplicationContext) for web application. So it is better to use ApplicationContext than BeanFactory.
Using BeanFactory
The XmlBeanFactory is the implementation class for the BeanFactory interface. To use the BeanFactory, we need to create the instance of XmlBeanFactory class as given below:
- Resource resource=new ClassPathResource("applicationContext.xml");
- BeanFactory factory=new XmlBeanFactory(resource);
The constructor of XmlBeanFactory class receives the Resource object so we need to pass the resource object to create the object of BeanFactory.
Using ApplicationContext
The ClassPathXmlApplicationContext class is the implementation class of ApplicationContext interface. We need to instantiate the ClassPathXmlApplicationContext class to use the ApplicationContext as given below:
- ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
The constructor of ClassPathXmlApplicationContext class receives string, so we can pass the name of the xml file to create the instance of ApplicationContext.
We can inject the dependency by constructor. The <constructor-arg> subelement of <bean> is used for constructor injection. Here we are going to inject
- primitive and String-based values
- Dependent object (contained object)
- Collection values etc.
Injecting primitive and string-based values
Let's see the simple example to inject primitive and string-based values. We have created three files here:
- Employee.java
- applicationContext.xml
- Test.java
Employee.java
It is a simple class containing two fields id and name. There are four constructors and one method in this class.
- package com.javatpoint;
- public class Employee {
- private int id;
- private String name;
- public Employee() {System.out.println("def cons");}
- public Employee(int id) {this.id = id;}
- public Employee(String name) { this.name = name;}
- public Employee(int id, String name) {
- this.id = id;
- this.name = name;
- }
- void show(){
- System.out.println(id+" "+name);
- }
- }
applicationContext.xml
We are providing the information into the bean by this file. The constructor-arg element invokes the constructor. In such case, parameterized constructor of int type will be invoked. The value attribute of constructor-arg element will assign the specified value. The type attribute specifies that int parameter constructor will be invoked.
- <?xml version="1.0" encoding="UTF-8"?>
- <beans
- xmlns="https://www.springframework.org/schema/beans"
- xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="https://www.springframework.org/schema/p"
- xsi:schemaLocation="https://www.springframework.org/schema/beans
- https://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
- <bean id="e" class="com.javatpoint.Employee">
- <constructor-arg value="10" type="int"></constructor-arg>
- </bean>
- </beans>
Test.java
This class gets the bean from the applicationContext.xml file and calls the show method.
- package com.javatpoint;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.*;
- public class Test {
- public static void main(String[] args) {
- Resource r=new ClassPathResource("applicationContext.xml");
- BeanFactory factory=new XmlBeanFactory(r);
- Employee s=(Employee)factory.getBean("e");
- s.show();
- }
- }
Output:10 null
Injecting string-based values
If you don't specify the type attribute in the constructor-arg element, by default string type constructor will be invoked.
- <bean id="e" class="com.javatpoint.Employee">
- <constructor-arg value="10"></constructor-arg>
- </bean>
- ....
If you change the bean element as given above, string parameter constructor will be invoked and the output will be 0 10.
Output:0 10
You may also pass the string literal as following:
- ....
- <bean id="e" class="com.javatpoint.Employee">
- <constructor-arg value="Sonoo"></constructor-arg>
- </bean>
- ....
Output:0 Sonoo
You may pass integer literal and string both as following
- ....
- <bean id="e" class="com.javatpoint.Employee">
- <constructor-arg value="10" type="int" ></constructor-arg>
- <constructor-arg value="Sonoo"></constructor-arg>
- </bean> Output:10 Sonoo
In cases of collection CI, if its list then define <list> tag. if it is map then define in <map> tag. e.g
- <map>
- <entry key="Java is a Platform" value="John Smith"></entry>
- <entry key="Java is an Island" value="Raj Kumar"></entry>
- </map>
Same way you can insert dependency into Object using Setter injection. In setter injection are <property> subelement of <bean> is used for setter injection.
There are many key differences between constructor injection and setter injection.
- Partial dependency: can be injected using setter injection but it is not possible by constructor. Suppose there are 3 properties in a class, having 3 arg constructor and setters methods. In such case, if you want to pass information for only one property, it is possible by setter method only.
- Overriding: Setter injection overrides the constructor injection. If we use both constructor and setter injection, IOC container will use the setter injection.
- Changes: We can easily change the value by setter injection. It doesn't create a new bean instance always like constructor. So setter injection is flexible than constructor injection.
All the above configuration metadata translates into a set of the following properties that make up each bean definition.
Properties |
Description |
class |
This attribute is mandatory and specify the bean class to be used to create the bean. |
name |
This attribute specifies the bean identifier uniquely. In XML-based configuration metadata, you use the id and/or name attributes to specify the bean identifier(s). |
scope |
This attribute specifies the scope of the objects created from a particular bean definition and it will be discussed in bean scopes chapter. |
constructor-arg |
This is used to inject the dependencies and will be discussed in next chapters. |
properties |
This is used to inject the dependencies and will be discussed in next chapters. |
autowiring mode |
This is used to inject the dependencies and will be discussed in next chapters. |
lazy-initialization mode |
A lazy-initialized bean tells the IoC container to create a bean instance when it is first requested, rather than at startup. |
initialization method |
A callback to be called just after all necessary properties on the bean have been set by the container. It will be discussed in bean lifecycle chapter. |
destruction method |
A callback to be used when the container containing the bean is destroyed. It will be discussed in bean life cycle chapter. |
Spring IoC container is totally decoupled from the format in which this configuration metadata is actually written. There are following three important methods to provide configuration metadata to the Spring Container:
- XML based configuration file.
- Annotation-based configuration
- Java-based configuration
Bean Scopes
Scope |
Description |
singleton |
This scopes the bean definition to a single instance per Spring IoC container (default). |
prototype |
This scopes a single bean definition to have any number of object instances. |
request |
This scopes a bean definition to an HTTP request. Only valid in the context of a web-aware Spring ApplicationContext. |
session |
This scopes a bean definition to an HTTP session. Only valid in the context of a web-aware Spring ApplicationContext. |
global-session |
This scopes a bean definition to a global HTTP session. Only valid in the context of a web-aware Spring ApplicationContext. |
Singleton:
If scope is set to singleton, the Spring IoC container creates exactly one instance of the object defined by that bean definition. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object.
The default scope is always singleton however, when you need one and only one instance of a bean, you can set the scope property to singleton in the bean configuration file, as shown below:
<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
<!-- collaborators and configuration for this bean go here -->
</bean>
Prototype:
If scope is set to prototype, the Spring IoC container creates new bean instance of the object every time a request for that specific bean is made. As a rule, use the prototype scope for all state-full beans and the singleton scope for stateless beans.
To define a prototype scope, you can set the scope property to prototype in the bean configuration file, as shown below:
<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
The life cycle of a Spring bean is easy to understand. When a bean is instantiated, it may be required to perform some initialization to get it into a usable state. Similarly, when the bean is no longer required and is removed from the container, some cleanup may be required.
Though, there is lists of the activities that take place behind the scenes between the time of bean Instantiation and its destruction, but this chapter will discuss only two important bean lifecycle callback methods which are required at the time of bean initialization and its destruction.
To define setup and teardown for a bean, we simply declare the <bean> with init-method and/or destroy-method parameters. The init-method attribute specifies a method that is to be called on the bean immediately upon instantiation. Similarly, destroy-method specifies a method that is called just before a bean is removed from the container.
Initialization callbacks:
The org.springframework.beans.factory.InitializingBean interface specifies a single method:
void afterPropertiesSet() throws Exception;
So you can simply implement above interface and initialization work can be done inside afterPropertiesSet() method as follows:
public class ExampleBean implements InitializingBean {
public void afterPropertiesSet() {
// do some initialization work
}
}
In the case of XML-based configuration metadata, you can use the init-method attribute to specify the name of the method that has a void no-argument signature. For example:
<bean id="exampleBean" .0000000000000000000
class="examples.ExampleBean" init-method="init"/>
Following is the class definition:
public class ExampleBean {
public void init() {
// do some initialization work
}
}
Destruction callbacks
The org.springframework.beans.factory.DisposableBean interface specifies a single method:
void destroy() throws Exception;
So you can simply implement above interface and finalization work can be done inside destroy() method as follows:
public class ExampleBean implements DisposableBean {
public void destroy() {
// do some destruction work
}
}
In the case of XML-based configuration metadata, you can use the destroy-method attribute to specify the name of the method that has a void no-argument signature. For example:
<bean id="exampleBean"
class="examples.ExampleBean" destroy-method="destroy"/>
Following is the class definition:
public class ExampleBean {
public void destroy() {
// do some destruction work
}
}
If you are using Spring's IoC container in a non-web application environment; for example, in a rich client desktop environment; you register a shutdown hook with the JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released.
It is recommended that you do not use the InitializingBean or DisposableBean callbacks, because XML configuration gives much flexibility in terms of naming your method.