Spring Framework Basics
- Understanding Dependency Injection
- Spring Bean Factory
- ApplicationContext and Property Initialization
- Constructor Injection
- Injection Objects
- Inner Beans and Aliases
- Initializing Collections
- Bean Autowiring
- Understanding Bean Scope
- Bean Definition Inheritance
Agenda
11. LifeCycle Callbacks
12. BeanPostProcessors
13. Annotations (Required,Autowired,JSR- 250,Component and Stereotype)
14. Java Based Configurations
What is Spring?
Why Spring?
What is Spring?
Spring is described as lightweight framework for building java applications.
The core of Spring Framework is based on the principle of Inversion of Control (IOC).
IOC is a technique that externalizes the creation and management of Component dependencies.
Spring acts like a container which provides instances of your application classes with all the dependencies they need.
A Spring managed resource is referred to as bean.
Problem if you don't use DI
Let us consider the example
Class Restaruant {
Tea tea = new Tea();
public void prepareHotDrink() {
tea.prepareHotDrink();
}
}
Problem 1: Replace Tea class with ExpressTea class Problem 2: Modifying the Tea class say Parameterising its constructor
Inverting control or Injecting dependencies
-
Reduced glue code
-
Simplified application configuration
-
The ability to manage common dependencies in a single repository
-
Good application design
Spring Framework
Steps for getting object from spring bean factory
(1) Configure the class in Spring XML
<bean id=“identifier“ class=“fully-qualified-class-name“/>
(2) Obtain the Instance of ApplicationContext type
ApplicationContext applicationContext=
new ClassPathXmlApplicationContext(“config.xml“)
(3) Getting instance of the registered class
ClassName obj= applicationContext.getBean(“identifier“,ClassName.class)
Example of getting bean from Spring Container
(1) Create a class Restaurant
Class Restaruant {
void greetings() {
System.out.println(“Welcome“);
}
}
(2) Configure the bean in XML file
<bean id=“restaruant“ class=“com.spring.demo.Restaraunt“/>
(3) Get instance from Spring Container
ApplicationContext ctx= newClassPathXmlApplicationContext(“config.xml“);
Restaruant restaruant = ctx.getBean(“restaruant“,Restaruant.class)
Ways to Initialize properties
-
Initialization using setter method
-
Constructor Initialization
Initialization throught setter method
Property tag is used inside the bean tag to set the values of the instance via setter methods.
<bean name=“identifier“ class=“fully-qaulified-class-name“>
<property name=“property-name“ value=“property-value“/>
…..
</bean>
Initialization throught setter method
-
Java Code
Class Restaruant {
String greetingMessage;
public void setGreetingMessage(String greetingMessage) {
this.greetingMessage=greetingMessage;
}
}
-
XML Configuration
<bean id=“restaruant“ class=“com.spring.demo.Restaraunt“>
<property name=“greetingMessage“ value=“Hello Customer“>
</bean>
Constructor Initialization
Constructor-arg tag is used inside bean tag to pass values to constructor parameter
<bean name=“identifier“ class=“fully-qaulified-class-name“>
<constructor-arg value=“value-passed-to-the constructor“/>
…..
</bean>
Construction Initialization Example
-
Java Code
Class Restaruant {
String greetingMessage;
Restaruant(String greetingMessage) {
this.greetingMessage=greetingMessage;
}
}
-
XML Configuration
<bean id=“restaruant“ class=“com.spring.demo.Restaraunt“>
<constructor-arg value=“Hello Customer“/>
</bean>
Other attributes for constructor-arg tag
-
name : name tag is used to specify the name of the parameter to whom we want to assign the value.
-
index : index specifies the order of the parameter to whom we want to assign the value.
-
type : type specifies the type of the parameter to whom we want to assign the value.
Index Example
-
Java Code
Class Restaruant {
String greetingMessage;
Integer restarauntNumber;
Restaruant(String greetingMessage,Integer restaraunt) {
this.greetingMessage=greetingMessage;
}
}
-
XML Configuration
<bean id=“restarauntBean“ class=“com.spring.demo.Restaraunt“>
<constructor-arg value=“Welcome Customer“ index=“0“>
<constructor-arg value=“1“ index=“1“>
</bean>
Type Example
-
Java Code
Class Restaruant {
String greetingMessage;
int restarauntNumber;
Restaruant(String greetingMessage, int restaraunt) {
this.greetingMessage=greetingMessage;
}
}
-
XML Configuration
<bean id=“restarauntBean“ class=“com.spring.demo.Restaraunt“>
<constructor-arg value=“Welcome Customer“ >
<constructor-arg value=“1“ type=“int“>
</bean>
Name Example
-
Java Code
Class Restaruant {
String greetingMessage;
int restarauntNumber;
Restaruant(String greetingMessage,int restaraunt) {
this.greetingMessage=greetingMessage;
}
}
-
XML Configuration
<bean id=“restarauntBean“ class=“com.spring.demo.Restaraunt“>
<constructor-arg value=“Welcome Customer“ name=“greetingMessage“>
<constructor-arg value=“1“ name=“restarauntNumber“>
</bean>
Exercise-1
-
Create a class Database with 2 instance variables port and name.
-
Configure Database class bean in spring container through Spring XML.
-
Initialize instance variables using setter method
-
Get the bean of the class from spring container and print the values of the instance variable
-
Initialize the instance variables with constructor initialization
Ref Attribute
Ref attribute is used inside the bean tag in order to assing value to a reference type under constructor-arg and property tag.
<bean id=“refBean“ class=“fully-qualified-name“/>
<bean name=“setterWay“ class=“fully-qualified-name“>
<property name=“property-name“ ref=“refBean“/>
</bean>
<bean name=“constructorWay“ class=“fully-qualified-name“>
<constructor-arg name=“property-name“ ref=“refBean“/>
</bean>
Ref Example
-
Java Code
public class Restaurant {
HotDrink hotDrink;
public Restaurant(HotDrink hotDrink) {
this.hotDrink = hotDrink;
}
}
-
XML Configuration
<bean id="tea" class="com.spring.demo.Tea"/>
//Tea class implements HotDrink interface
<bean id="restaurant" class="com.spring.demo.Restaurant">
<constructor-arg ref="tea"/>
</bean>
Inner Beans
If the bean which we are creating is just used a component of another bean then we can create an inner bean in the following way
<bean id=“identifier“ class=“fully-qualified-name“>
<property name=“property-name“>
<bean class=“fully-qualified-name“>
</property>
</bean>
Inner Bean Example
-
Java Code
public class Restaurant {
HotDrink hotDrink;
public Restaurant(HotDrink hotDrink) {
this.hotDrink = hotDrink;
}
}
-
XML Configuration
<bean id="restaurant" class="com.spring.demo.Restaurant">
<constructor-arg>
<bean id="tea" class="com.spring.demo.Tea"/>
</constructor-arg>
</bean>
Aliasing a bean
In place of “id“ attribute in bean tag you can also use “name“ attribute to provide an identifier to bean. In case of using name attribute you can give multiple alias name seperated by space.
<bean id=“identifier“ class=“fully-qualified-class-name“
name=“alias1 alias2 alias3 alias4“/>
Alias tag can also be used to provide an alernative identifier to bean using following way.
<alias name=“identifier“ alias=“alias-identifier“/>
Exercise-2
-
Create a class Restaurant
-
Create an interface HotDrink with an abstract method prepareHotDrink
-
Create two classes Tea and ExpressTea which implements HotDrink Class
-
Create an instance variable of type HotDrink in Restaurant class.
-
Configure Tea and ExpressTea classes beans in Spring XML
-
create a bean with the name teaRestaurant of type Restaurant which inject Tea object as dependency using setter method.
-
create a bean with the name expressTeaRestaurant of type Restaurant which inject ExpressTea object as dependency using Constructor initialization.
-
Get both the beans and invoke prepareHotDrink method via hotDrink instance variables
-
Try inner bean with expressTeaRestaurant.
-
Create alias of teaRestaurant bean and access it through alias name.
Collection Initialization
-
List
<bean id=“identifier“ name=“fully-qualified-class-name“>
<property name=“list-type-property“>
<list>
<value>value1</value>
<value>value2</value>
</list>
</property>
</bean>
-
Set
<bean id=“identifier“ name=“fully-qualified-class-name“>
<property name=“set-type-property“>
<set>
<value>value1</value>
<value>value2</value2>
</set>
</property>
</bean>
Collection Initialization (cont.)
<bean id=“identifier“ name=“fully-qualified-class-name“>
<property name=“map-type-property“>
<map>
<entry key="key-1" value="value-1"/>
<entry key="key-2" value="value-2"/>
</map>
</property>
</bean>
-
Map
Example of initialization
-
Java Code
class complex {
List list;
Set set;
Map map;
}
-
XML Configuration
<bean id="complexObject" class="com.spring.demo.Complex">
<property name="list">
<list>
<value>1</value>
<value>2</value>
<value>3</value>
</list>
</property>
<property name="set">
<set>
<value>2</value>
<value>3</value>
</set>
</property>
Example of initialization (Cont.)
<property name="map">
<map>
<entry key="1" value="One"/>
<entry key="2" value="Two"/>
</map>
</property>
</bean>
Bean Autowiring
-
ByName: Spring looks for a bean with the same name as the property that needs to be autowired.
-
ByType: Allows a property to be autowired if exactly one bean of the property type exists in the container.
-
Constructor: Analogous to byType, but applies to constructor arguments.
<bean id=“identifier“ class=“fully-qualified-class-name“ autowire=“byName“/>
Bean Autowiring Example
-
byName
<bean id=“restaurant“ class=“com.spring.demo.Restaurant“autowire=“byName“/>
<bean id=“hotDrink“ class=“com.spring.demo.Tea“>
-
constructor
<bean id=“restaurant“ class=“com.spring.demo.Restaurant“ autowire=“constructor“/>
<bean id=“tea“ class=“com.spring.demo.Tea“>
-
byType
<bean id=“restaurant“ class=“com.spring.demo.Restaurant“ autowire=“byType“/>
<bean id=“tea“ class=“com.spring.demo.Tea“>
Bean Scope
Basic Bean Scope
-
Singleton : Only once per spring container
-
Prototype : New bean created with every request or reference
Web-aware Context Bean Scope
-
Request : New bean per servlet request
-
Session : New bean per session
<bean id=“identifier“ class=“fully-qualified-class-name“ scope=“singleton“/>
Bean Scope Example
-
XML Configuration
<bean id="restaurant" class="com.spring.demo.Restaurant" scope="singleton">
<property name="hotDrink" ref="tea"/>
</bean>
-
Java Code
ApplicationContext ctx = new ClassPathXmlApplicationContext("config.xml");
System.out.println(ctx.isPrototype("restaurant"));
Exercise-3
- Create Class Complex as follows:
class complex {
List list;
Set set;
Map map;
}
generate getter and setters for Complex class
- Initialize all the instance variables of the complex class using Spring XML. Give bean name as complexBean. Get the bean and display the properties.
- Autowire hotDrink in Restaurant with tea bean byName, byType and constructor.
- Set the scope of the teaRestaurant bean as proptotype and check the scope type after accessing the bean.
Bean Defination Inheritance
A child Bean defination inherits configuration data from a parent defination.
<bean id=“parentBean“ class=“fully-qaulified-class-name“>
<property name=“property-name1“ value=“property-value1“/>
</bean>
<bean id=“childBean“ class=“fully-qualified-class-name“ parent=“parentBean“>
<property name=“property-name2“ value=“property-value2“/>
</bean>
Bean Defination Inheritance Example
<bean id="parent-triangle" class="com.spring.demo.Triangle">
<property name="a" ref="aPoint"/>
</bean>
<bean id="triangle" class="com.spring.demo.Triangle" parent="parent-triangle">
<property name="b" ref="bPoint"/>
<property name="c" ref="cPoint"/>
</bean>
Lifecycle Callbacks
We can track the initialization and destruction of the bean by following ways
-
Using InitializingBean and DisposableBean interfaces
-
Using init-method and destroy-method attributes of bean tag
<bean id=“identifier“ init-method=“method-name“ destroy-method=“method-name“/>
-
PostConstruct and PreDestroy Annotations
Note : In order to use PostContruct and PreDestroy annotation place following line Spring Configuration file.
<bean
class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
Note: In order to enable invoking of destroy method you'll need to invoke ConfigurableApplicationContext#registerShutdownHook()
BeanPostProcessor
-
BeanPostProcessor is an interface that provides callbacks which are executed before and after the initialization of the bean.
-
The class in which we are implementing BeanPostProcessor interface must be configured in Spring Container.
-
Name of the callback methods are postProcessAfterInitialization and postProcessBeforeInitialization.
-
default-lazy-init attribute in the beans tag can be used to control the intialization of beans at once.
Exercise-4
-
Create a class Point with 2 instance variables xAxis and yAxis of type integer.
-
Create a class triangle which contains 3 instance variables of type Point i.e pointA, pointB and pointC
-
Create a parentTriangle bean which initializes pointA.
-
Create a triangleBean which inherits parentTriangleBean and initializes pointB and pointC.
-
Call the Lifecycle callback methods of triangle beans using all the 3 methods.
-
Implement BeanPostProcessor.
Required Annotation
-
@Required annotation is used to make sure that the property has been set in the bean or else it will throught the exception.
-
This annotation can be used with setter method.
-
Place following line in spring configuration in order to get the functionality of @Require:
<bean
class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
Autowire Annotation
-
With the help of autowire annotation you can wire a bean with dependent Object.
-
By Default it looks for type of bean. If more than one type of bean is found then it looks for bean by name. If it does not find any compatible bean then exception is generated.
-
AutowiredAnnotationBeanPostProcessor needs to be configured in Spring container if you want to use this annotation:
-
@Autowire can be used with field, constructor and setter method
<bean
class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
XML Configuration
In spite of registering each and every class for annotation you can simply place
<context:annotation-config/>
inside spring configuration file.
To enable the support for annotation-config:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
JSR-250 annotations
- Resource : Resource annotation serves the same purpose as Autowired but it cannot be used with constructor.
- PostContruct : Method marked with this annotation is invoked after the object has been initialized.
- PreDestroy : Method marked with this annotation is invoked before the object is destroyed.
Component and Stereotype Annotations
Following annotations configures the class as a spring bean inside the spring container.
- Component
- Service
- Controller
- Repository
In order to scan all the beans you need to place following statement in spring configuration file.
<context:component-scan base-package=“package-name“>
Exercise-5
-
Use @Required annotation for hotDrink setter method in Restaurant class.
-
Use @Autowired annotation to wire Tea with Restaurant class Using setter method, field and constructor.
-
Use @Component, @Controller, @Repository etc annotation to configure Tea and Restaurant in Spring Container.
Java Based Container configurations
-
@Configuration
-
@Bean
-
@Scope
@Configuration
@Configuration is a class level annotation indicating that an Object is a source of bean definitions.
@Configuration
class AppConfig{
}
@Bean
-
To declare a bean simple annotate a method with @Bean annotation.
-
This method is then used to register a bean definition within an ApplicationContext of the type specified as the method’s return value
-
initMethod and destroyMethod attributes can be used specify init and destroy methods.
@Bean(initMethod = "initMethod",destroyMethod = "destroyMethod")
@Bean (Cont.)
@Configuration
public class AppConfig {
@Bean
Database database() {
Database database = new Database();
database.setName("mysql");
database.setPort(3306);
return database;
}
}
Equals
<beans>
<bean id=“database“ class=“com.spring.demo.Database“>
<property name=“port“ value=“3306“>
<property name=“name“ value=“mysql“>
</bean>
<beans>
Accessing a bean from @Configuration class
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
Database database = applicationContext.getBean("database",Database.class);
@Scope
This annotation can be used to set the scope of the bean as follows:
@Configuration
public class AppConfig {
@Scope(“prototype“)
@Bean
Database database() {
Database database = new Database();
database.setName("mysql");
database.setPort(3306);
return database;
}
}
Exercise-6
-
Create a class AppConfig.Java and mark it with @Configuration annotation.
-
Declare two beans of Database class inside AppConfig using the bean annotation. Name one bean mysql and other bean oracle.
-
Declare init and destroy method for oracle bean with the help of Bean annotation.
-
Set the scope of mysql bean as prototype.
-
Access and display the value of both the beans.
Thank you :)
Spring Framework Basics
By Pulkit Pushkarna
Spring Framework Basics
- 2,438