Agenda
11. LifeCycle Callbacks
12. BeanPostProcessors
13. Annotations (Required,Autowired,JSR- 250,Component and Stereotype)
14. Java Based Configurations
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.
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
Reduced glue code
Simplified application configuration
The ability to manage common dependencies in a single repository
Good application design
(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)
(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)
Initialization using setter method
Constructor Initialization
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>
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-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>
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>
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.
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>
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>
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>
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 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>
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>
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>
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>
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“/>
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.
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>
<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
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>
<property name="map">
<map>
<entry key="1" value="One"/>
<entry key="2" value="Two"/>
</map>
</property>
</bean>
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“/>
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“>
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“/>
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"));
class complex {
List list;
Set set;
Map map;
}
generate getter and setters for Complex class
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 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>
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 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.
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 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"/>
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"/>
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>
Following annotations configures the class as a spring bean inside the spring container.
In order to scan all the beans you need to place following statement in spring configuration file.
<context:component-scan base-package=“package-name“>
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.
@Configuration
@Bean
@Scope
@Configuration is a class level annotation indicating that an Object is a source of bean definitions.
@Configuration
class AppConfig{
}
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")
@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>
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
Database database = applicationContext.getBean("database",Database.class);
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;
}
}
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.