Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
searching extra learning contents which you may search later after reading the book completely. Or you
can search it in office as you have all the available resource like system, big spring mvc TAP project, and
big spring framework based applications like ArchiveFiletransfer utility. But, at home only read the book.
TIME IS MONEY
Core Spring
Inversion of Control using xml (old technique):-
To work with xml spring configuration, we need *.xml file from where ApplicationContext will load all
the beans from the xml file to spring container.
MotorCar.java
package com.bean;
public class MotorCar {
private int engineNo;
public MotorCar()
{
engineNo=000;
}
public void showEngine()
{
System.out.println("The engine Number is: "+engineNo);
}
}
mySpring-config.xml
This is the xml config file where ApplicationContext will search for the beans.
CarDemoApp.java
package com.apps;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bean.MotorCar;
public class CarDemoApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new
ClassPathXmlApplicationContext("mySpring-config.xml");
MotorCar car=context.getBean("car",MotorCar.class);
car.showEngine();
}
}
This is the Application where main() function defined and from here our application will load. Here,
ClassPathXmlApplicationContext is actually the Spring container.
Spring Container Does Two Things
Stick to the book(Spring in Action, 4th Edition) and Chad/Kaushik/Navin because unknowingly you are
wasting lot of time searching extra learning contents which you may search later after reading the book
completely. Or you can search it in office as you have all the available resource like system, big spring
mvc TAP project, and big spring framework based applications like ArchiveFiletransfer utility. But, at
home only read the book.
TIME IS MONEY
In the above example, we just covered the Inversion of Control using xml.
MotorCar.java
package com.bean;
public class MotorCar {
private int engineNo;
public MotorCar()
{
engineNo=000;
}
public void showEngine()
{
System.out.println("The engine Number is: "+engineNo);
}
}
Step 2:- Configuring Spring Beans
CarDemoApp.java
package com.apps;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.MotorCar;
@Configuration
public class CarDemoApp {
@Bean
MotorCar getCar()
{
return new MotorCar();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CarDemoApp.class);
MotorCar car=context.getBean(MotorCar.class);
car.showEngine();
context.close();
}
}
CarDemoApp .java
package com.apps;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.MotorCar;
@Configuration
public class CarDemoApp {
@Bean
MotorCar getCar()
{
return new MotorCar();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CarDemoApp.class);
MotorCar car=context.getBean(MotorCar.class);
car.showEngine();
context.close();
}
}
TIME IS MONEY
In this example we are loading two different car i.e. myCar and yourCar of MotorCar.class into spring
container.
CarDemoApp.java
package com.apps;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.MotorCar;
@Configuration
public class CarDemoApp {
@Bean(name="myCar")
MotorCar getCar()
{
return new MotorCar();
}
@Bean(name="yourCar")
MotorCar getYourCar()
{
System.out.println("In your car");
return new MotorCar();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CarDemoApp.class);
MotorCar car=context.getBean("myCar",MotorCar.class);
MotorCar car1=context.getBean("yourCar",MotorCar.class);
car.showEngine();
car1.showEngine();
context.close();
}
}
Spring Dependency Injection using xml configuration
Suppose, our MotorCar has different types Engine.
MyEngine.java
package com.bean;
public class MyEngine {
private int engineNo;
public MyEngine(int number)
{
engineNo=number;
}
public String toString()
{
return("The Engine is "+engineNo);
}
}
MotorCar.java
package com.bean;
public class MotorCar {
private MyEngine fastEng;
public MotorCar(MyEngine eng)
{
fastEng=eng;
}
public void showEngine()
{
System.out.println("The Car detail::: \n"+fastEng);
}
}
mySpring-config.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"
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">
<bean name="car" class="com.bean.MotorCar">
<constructor-arg ref="engine1" />
</bean>
<bean name="engine1" class="com.bean.MyEngine">
<constructor-arg value="1234" />
</bean>
</beans>
CarDemoApp.java
package com.apps;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bean.MotorCar;
public class CarDemoApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new
ClassPathXmlApplicationContext("mySpring-config.xml");
MotorCar car=context.getBean("car",MotorCar.class);
car.showEngine();
context.close();
}
}
MyEngine .java
package com.bean;
public class MyEngine {
private int engineNo;
public MyEngine(int number)
{
engineNo=number;
}
public String toString()
{
return("The Engine is "+engineNo);
}
}
MotorCar .java
package com.bean;
public class MotorCar {
private MyEngine fastEng;
public MotorCar(MyEngine eng)
{
fastEng=eng;
}
public void showEngine()
{
System.out.println("The Car detail::: \n"+fastEng);
}
}
CarDemoApp .java
package com.apps;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.MotorCar;
import com.bean.MyEngine;
@Configuration
public class CarDemoApp {
@Bean(name="myCar")
MotorCar getCar()
{
System.out.println("In my car");
return new MotorCar(getMyEngine());
//Alternate way return new MotorCar(new MyEngine(7564));
}
@Bean(name="yourCar")
MotorCar getYourCar()
{
System.out.println("In your car");
return new MotorCar(getYourEngine());
//Alternate way return new MotorCar(new MyEngine(8564));
}
@Bean(name="myEngine")
MyEngine getMyEngine()
{
return new MyEngine(7564);
}
@Bean(name="yourEngine")
MyEngine getYourEngine()
{
return new MyEngine(8564);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CarDemoApp.class);
MotorCar car=context.getBean("myCar",MotorCar.class);
MotorCar car1=context.getBean("yourCar",MotorCar.class);
car.showEngine();
car1.showEngine();
context.close();
}
}
CarDemoApp .java
package com.apps;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.MotorCar;
import com.bean.MyEngine;
@Configuration
public class CarDemoApp {
@Bean(name="myCar")
MotorCar getCar()
{
System.out.println("In my car");
return new MotorCar(getMyEngine());
//Alternate way return new MotorCar(new MyEngine(7564));
}
@Bean(name="yourCar")
MotorCar getYourCar()
{
System.out.println("In your car");
return new MotorCar(getYourEngine());
//Alternate way return new MotorCar(new MyEngine(8564));
}
@Bean(name="myEngine")
MyEngine getMyEngine()
{
return new MyEngine(7564);
}
@Bean(name="yourEngine")
MyEngine getYourEngine()
{
return new MyEngine(8564);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CarDemoApp.class);
MotorCar car=context.getBean("myCar",MotorCar.class);
MotorCar car1=context.getBean("yourCar",MotorCar.class);
car.showEngine();
car1.showEngine();
context.close();
}
}
MyEngine .java
package com.bean;
public class MyEngine {
private int engineNo;
public MyEngine(int number)
{
engineNo=number;
}
public String toString()
{
return("The Engine is "+engineNo);
}
}
MotorCar .java
package com.bean;
public class MotorCar {
private MyEngine fastEng;
public MotorCar(MyEngine eng)
{
fastEng=eng;
}
public void showEngine()
{
System.out.println("The Car detail::: \n"+fastEng);
}
}
mySpring-config.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"
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">
<bean name="car" class="com.bean.MotorCar">
<property name="fastEng" ref="engine1" />
</bean>
<bean name="engine1" class="com.bean.MyEngine">
<property name="engineNo" value="1234" />
</bean>
</beans>
CarDemoApp.java
Using spring container ClassPathXmlApplicationContext.
MotorCar.java MyEngine.java
This is our beans and MotorCar has MyEngine.
MyCarFactory.java
JAVA annotation config done using @Bean and @Configuration annotation.
CarDemoApp.java
Using spring container AnnotationConfigApplicationContext . Now,
ApplicationContext will load the config beans from MyCarFactory class.
Stick to the book(Spring in Action, 4th Edition) and Chad/Kaushik/Navin because unknowingly you are
wasting lot of time searching extra learning contents which you may search later after reading the book
completely. Or you can search it in office as you have all the available resource like system, big spring
mvc TAP project, and big spring framework based applications like ArchiveFiletransfer utility. But, at
home only read the book.
TIME IS MONEY
Injection from Property File (via xml)
This is actually using setter method internally to inject value from property file.
MyEngine.java MotorCar.java
This is our beans and MotorCar has MyEngine.
mySpring-config.xml
Using <property> for setter injection.
carFeature.properties
CarDemoApp.java
Using spring container ClassPathXmlApplicationContext.
TIME IS MONEY
Ans. previously, we need to explicitly tell spring whichever the bean by @Bean. Now, we don’t need to write
@Bean and all the Bean getter methods at config class. (So much of coding)
We need three annotations, @Configuration and @ComponentScan to specify the config file and
automatically scanning for the beans in the current package where the Annotation config class is
written.
@Component to specify the bean which will be loaded as spring bean container.
RunDemoApp.java
HexaCar bean loaded as it defines with @Component annotation.
Introducing multiple basePackages in application config file.
MyEngine.java
This is our new bean which will loaded by
@ComponentScan(basePackages={"com.bean","com.pojo"}) from com.pojo package.
RunDemoApp.java
Loading multiple beans from multiple packages into spring container.
@Autowired , @Component for autowiring member beans and to create beans into spring
container.
If the autowired beans’ package is not @Component scanned then we may get the following
error.
org.springframework.beans.factory.BeanCreationException: Injection of autowired
dependencies failed;
Whether it’s a constructor, a setter method, or any other method, Spring will attempt to satisfy
the dependency expressed in the method’s parameters. Assuming that one and only one bean
matches, that bean will be wired in.
NOTE:-
@Named can be used in place of @Component.
@Inject can be used in place of @Autowired.
There are some more autowiring ambiguities that we will discuss later.
Wiring beans with XML (p-46, manning spring in action: It’s a great book)
With JavaConfig, that meant creating a class annotated with @Configuration. For XML
configuration, that means creating an XML file rooted with a <beans> element.
</beans>
applicationConetxt.xml
Here, we have defined a student bean without an id (!!!Surprised!!!).
Student.java
This is the Student pojo.
CollegeApp.java
This is our testing class. Here, the default id that spring defined for Student is
“com.bean.Student#0” as we did not mention any id for Student <bean> tag.
If you were to declare another SgtPeppers bean without explicitly identifying it, it would
automatically be given an ID of “com.bean.Student#1”.
XML configuration is less powerful than JavaConfig, where you can do almost anything
imaginable to arrive at the bean instance.
Spring’s XML configuration doesn’t benefit from compile-time verification of the Java types
being referred to.
To enable our xml configuration with c-namespace feature, we need the below extra schema
definition.
xmlns:c="http://www.springframework.org/schema/c"
Student.java
package com.bean;
public class Student {
private Address address;
public Student(Address add)
{
this.address=address;
}
public Address getAddress() {
return address;
}
}
Address.java
package com.bean;
public class Address {
private String street;
public Address()
{
street="My address";
}
public String toString()
{
return ("Address: "+street);
}
}
CollegeApp.java
package com.myTest;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bean.Student;
public class CollegeApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new
ClassPathXmlApplicationContext("applicationConetxt.xml");
Student student=context.getBean("myStudent",Student.class);
System.out.println(student.getAddress());
}
}
Let’s modify applicationConetxt.xml a bit because we have only one constructor here.
So no need to mention the argument name.
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student' c:_-ref='stuAdd'/>
<bean id='stuAdd' class='com.bean.Address'/>
</beans>
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student'>
<constructor-arg value='Sumit'/>
<constructor-arg value='19'/>
</bean>
</beans>
Student.java
package com.bean;
public class Student {
private String name;
private int age;
public Student(String theName,int theAge)
{
name=theName; age=theAge;
}
public String toString()
{
return ("Name: "+name+" Age: "+age);
}
}
Injecting literal through c-namespace in spring
When it comes to wiring bean reference and literal values, both <constructor-arg>
and the c-namespace attributes are equally capable.
applicationConetxt.xml
So, in the case of c-namespace also spring does the automatic type conversion from String to
int for ‘theAge’ parameter here.
Student.java
package com.bean;
public class Student {
private String name;
private int age;
private Address address;
public Student(String theName,int theAge,Address add)
{
name=theName;age=theAge;address=add;
}
public String toString()
{
return ("Name: "+name+" Age: "+age+" Address: "+address);
}
}
Address.java
package com.bean;
public class Address {
private String street;
public Address()
{
street="My address";
}
public String toString()
{
return ("Address: "+street);
}
}
CollegeApp.java
package com.myTest;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.bean.Student;
public class CollegeApp {
public static void main(String[] args) {
ClassPathXmlApplicationContext context=new
ClassPathXmlApplicationContext("applicationConetxt.xml");
Student student=context.getBean("myStudent",Student.class);
System.out.println(student.toString());
}
}
With c-namespace
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student'
c:theName="Sumit"
c:theAge="19"
c:add-ref='theAddr'
/>
<bean name='theAddr' class='com.bean.Address'/>
</beans>
But there’s one thing that <constructor-arg> can do that the c-namespace can’t do.
Let’s look at how to wire collections to constructor arguments.
WIRING COLLECTIONS
Suppose, Student.java class has list of subjects. Let’s see how to wire a list through constructor.
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student'>
<constructor-arg value='Sumit'/>
<constructor-arg value='30'/>
<constructor-arg>
<list>
<value>Chemistry</value>
<value>Physics</value>
</list>
</constructor-arg>
</bean>
</beans>
Student.java
package com.bean;
import java.util.List;
public class Student {
private String name;
private int age;
private List<String> subjects;
public Student(String theName,int theAge,List<String> theSubjects)
{
name=theName;age=theAge;subjects=theSubjects;
}
public String toString()
{
System.out.println("Subjects: ");
for(String str:subjects)
System.out.println(str);
return ("Name: "+name+" Age: "+age);
}
}
Address.java CollegeApp.java
This two becomes unchanged.
Let’s see how we can refer to another class for List.
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student'>
<constructor-arg value='Sumit'/>
<constructor-arg value='30'/>
<constructor-arg>
<list>
<ref bean='permAdd'/>
<ref bean='resAdd'/>
</list>
</constructor-arg>
</bean>
<bean name='permAdd' class='com.bean.Address' c:theStreet='Permanent
Address'/>
<bean name='resAdd' class='com.bean.Address' c:theStreet='Residential
Address'/>
</beans>
Student.java
package com.bean;
import java.util.List;
public class Student {
private String name;
private int age;
private List<Address> addresses;
public Student(String theName,int theAge,List<Address> theAddrs)
{
name=theName;age=theAge;addresses=theAddrs;
}
public String toString()
{
System.out.println("Addresses: ");
for(Address addr:addresses)
System.out.println(addr);
return ("Name: "+name+" Age: "+age);
}
}
Address.java CollegeApp.java
This two are unchanged.
Setting properties
CollegeApp.java
Our testing application class has no changes.
We can declare Null inside a <constructor-arg> if we don’t want to set List property value.
<constructor-arg><null/></constructor-arg>
Suppose, name and age has hard dependency (constructor injection) and address is an
optional dependency (setter injection). We have both constructor and setter injection at a time.
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student' c:theName='Sumit' c:theAge='30'>
<property name='address' ref='theAddr'/>
</bean>
<bean name='theAddr' class='com.bean.Address' c:theStreet='permanent
address'/>
</beans>
Student.java
package com.bean;
public class Student {
private String name;
private int age;
private Address address;
public Student(String theName,int theAge)
{
name=theName;age=theAge;
}
public void setAddress(Address address) {
this.address = address;
}
public String toString()
{
return ("Name: "+name+" Age: "+age+address);
}
}
Address.java
package com.bean;
public class Address {
private String street;
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address: "+street);
}
}
CollegeApp.java
Testing app is unchanged.
To parse this p-namespace syntax, we need the below new schema in xml.
xmlns:p="http://www.springframework.org/schema/p"
Suppose, Student has name, age and address as optional dependency (setter injection). But,
Address still has street as hard dependency (constructor injection). We need two extra
schemas. xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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">
<bean id="myStudent" class='com.bean.Student' p:name='Sumit' p:age='30'
p:address-ref='theAddr'/>
<bean name='theAddr' class='com.bean.Address' c:theStreet='permanent
address'/>
</beans>
Student.java
package com.bean;
public class Student {
private String name;
private int age;
private Address address;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setAddress(Address address) {
this.address = address;
}
public String toString()
{
return ("Name: "+name+" Age: "+age+address);
}
}
Address.java CollegeApp.java
This is unchanged.
But there’s one thing that <property> can do that the p-namespace can’t do. (without using util-
namespace)
Let’s look at how to wire collections to setter injection.
Student.java
package com.bean;
import java.util.List;
public class Student {
private String name;
private int age;
private List<String> subjects;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSubjects(List<String> subjects) {
this.subjects = subjects;
}
public String toString()
{
System.out.println("Subjects: ");
for(String str:subjects)
System.out.println(str);
return ("Name: "+name+" Age: "+age);
}
}
CollegeApp.java
Testing application is unchanged.
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
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">
<bean id="myStudent" class='com.bean.Student' p:name='Sumit' p:age='30'>
<property name='addresses'>
<list>
<ref bean='pAddress'/>
<ref bean='rAddress'/>
</list>
</property>
</bean>
<bean name='pAddress' class='com.bean.Address' p:street='permanent address'/>
<bean name='rAddress' class='com.bean.Address' p:street='residential
address'/>
</beans>
Student.java
package com.bean;
import java.util.List;
public class Student {
private String name;
private int age;
private List<Address> addresses;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
public String toString()
{
System.out.println("Addresses: ");
for(Address addr:addresses)
System.out.println(addr);
return ("Name: "+name+" Age: "+age);
}
}
Address.java
package com.bean;
public class Address {
private String street;
public void setStreet(String street) {
this.street = street;
}
public String toString()
{
return (" Address: "+street);
}
}
CollegeApp.java
This remains unchanged.
There’s no convenient way to specify a list of values (or bean references) with the p-
namespace. But you can take advantage of something from Spring’s util-namespace to simplify
the Student bean.
applicationConetxt.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
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
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="myStudent" class='com.bean.Student' p:name='Sumit' p:age='30'
p:subjects-ref='subjectList'/>
<util:list id='subjectList'>
<value>Physics</value>
<value>Chemistry</value>
</util:list>
</beans>
Student.java
package com.bean;
import java.util.List;
public class Student {
private String name;
private int age;
private List<String> subjects;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSubjects(List<String> subjects) {
this.subjects = subjects;
}
public String toString()
{
System.out.println("Subjects: ");
for(String str:subjects)
System.out.println(str);
return ("Name: "+name+" Age: "+age);
}
}
CollegeApp.java
This remains unchanged.
CollegeApp.java
This remains unchanged.
Student.java Address.java
This is our beans. Notice that Address has @Component annotation
Why? Because, Student is autowiring the Address bean.
AddressAppConfig.java StudentAppConfig.java
This is our configuration for Address and
Student.
applicationConetxt.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:c="http://www.springframework.org/schema/c"
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">
<bean name='address' class='com.bean.Address' c:theStreet='Residential
Address'></bean>
</beans>
Suppose, we want to load all configurations from an xml file. Then we need to design
ApplicationContext.xml. Let’s see the changes below.
applicationConetxt.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:c="http://www.springframework.org/schema/c"
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">
<bean name='student' class='com.bean.Student' c:theName='Sumit'
c:theAge='30'></bean>
<bean name='address' class='com.bean.Address' c:theStreet='Residential
Address'></bean>
</beans>
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import com.bean.Student;
@Configuration
@ImportResource("classpath:applicationConetxt.xml")
public class CollegeApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
Student.java Address.java
This remains unchanged.
Suppose, we want to load all configurations to one xml file from another xml file. Then we need
to design another config xml file and import that xml file to ApplicationContext.xml. Let’s see the
changes below.
applicationConetxt.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:c="http://www.springframework.org/schema/c"
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">
<import resource='address-config.xml'/>
<bean name='student' class='com.bean.Student' c:theName='Sumit'
c:theAge='30'></bean>
</beans>
address-config.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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name='address' class='com.bean.Address' c:theStreet='Residential
Address'></bean>
</beans>
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import com.bean.Student;
@Configuration
@ImportResource("classpath:applicationConetxt.xml")
public class CollegeApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
Student.java Address.java
This remains unchanged.
However, there will not be any injection we are using here. As a result, toSpring() returns null
objects. In this way we can quickly set up our application where we don’t need any @Bean
configurations for every class to load as spring bean.
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Student;
@Configuration
@ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
Student.java Address.java
This is our beans which must be defined with @Component.
To make our quick application more dynamic, we can use @Autowired annotation for loading
Address along with @Component and @ComponentScan.
Important points
1) Sometimes, @Component may leads to a problem where it might say no default constructor
found.
The class which is defined as a @Component annotation, it must have a default constructor.
2) Suppose, we have applied @Autowired annotation at field which is a user defined class
reference.
Now, if we also apply @Component to that class then it will always be initialized with null.
So, a field with @Autowired should not have @Component at its class definition.
3) By default @Autowired is byType.
Example project:-
Address bean is autowired at Student class.
Let’s see what happens if we apply @Component at Address.java.
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import com.bean.Address;
import com.bean.Student;
//Component scanning will for only those classes
//which is defined as @Component. But, all the class should not use
//@Component always even if the class is enabled with auto
//component scanning in configuration class, specially the class which is Autowired
//Or which is a property of another class
@Configuration
@ComponentScan(basePackages={"com.bean"})
public class CollegeApp {
@Bean
public Address getAddress(){
return new Address("Elgin street");
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
To resolve the issue, only change the Address.java as below by removing @Component.
Address.java
package com.bean;
public class Address {
private String street;
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Output:-
Name:null Age:0 Address:Elgin street
@Autowired Ambiguities
There are three beans as below.
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.ByCycle;
import com.bean.MotorBike;
import com.bean.Student;
import com.bean.Vehicle;
@Configuration
public class CollegeApp {
@Bean
public Vehicle getByCycle()
{
return new ByCycle();
}
@Bean
public Vehicle getMotorBike()
{
return new MotorBike();
}
@Bean
public Student getStudent()
{
return new Student("Sumit", 30);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
To resolve the issue, we have to first name each of the bean of different implementations.
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.ByCycle;
import com.bean.MotorBike;
import com.bean.Student;
import com.bean.Vehicle;
@Configuration
public class CollegeApp {
@Bean(name="byCycle")
public Vehicle getByCycle()
{
return new ByCycle();
}
@Bean(name="Bike")
public Vehicle getMotorBike()
{
return new MotorBike();
}
@Bean
public Student getStudent()
{
return new Student("Sumit", 30);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
Even if we differentiate the bean name, @Autowired is default byType. So it again finds multiple
type Vehicle as bean in spring container.
There is no specific way to tell spring to use @Autowired byname while using annotation.
But, there is one another way that spring @Autowired annotation works.
Way 1
Spring first check with byType while finding the @Autowired bean. If it finds same type multiple
beans, spring then searches for the matching name byname which is vehicle in this case.
So if we named our one of the Vehicle bean as “vehicle”, spring will resolve the Student class
@Autowired binding with that bean.
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.ByCycle;
import com.bean.MotorBike;
import com.bean.Student;
import com.bean.Vehicle;
@Configuration
public class CollegeApp {
@Bean(name="byCycle")
public Vehicle getByCycle()
{
return new ByCycle();
}
@Bean(name="vehicle")
public Vehicle getMotorBike()
{
return new MotorBike();
}
@Bean
public Student getStudent()
{
return new Student("Sumit", 30);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
Way 2
Tell spring specifically that which bean it should choose for Autowiring at the time of
@Autowired by using @Qualifier annoatation.
Student.java
package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class Student {
private String name;
private int age;
@Autowired
@Qualifier("Bike")
private Vehicle vehicle;
public Student(String theName,int theAge)
{
name=theName;age=theAge;
}
public String toString()
{
return ("Name:"+name+" Age:"+age+" has to do "+vehicle.move());
}
}
CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.bean.ByCycle;
import com.bean.MotorBike;
import com.bean.Student;
import com.bean.Vehicle;
@Configuration
public class CollegeApp {
@Bean(name="byCycle")
public Vehicle getByCycle()
{
return new ByCycle();
}
@Bean(name="Bike")
public Vehicle getMotorBike()
{
return new MotorBike();
}
@Bean
public Student getStudent()
{
return new Student("Sumit", 30);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(CollegeApp.class);
Student student=context.getBean(Student.class);
System.out.println(student.toString());
context.close();
}
}
When .properties file is inside the classpath then below should be the code.
MyPropConfig.java
package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@Configuration
@PropertySource("classpath:myPropNew.properties")
public class MyPropConfig {
@Autowired
Environment env;
public void showPropVal()
{
System.out.println("User name::"+env.getProperty("user.num")+"
Age::"+env.getProperty("user.age"));
}
}
PropertyDemoApp.java
package com.demo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class PropertyDemoApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =new
AnnotationConfigApplicationContext(MyPropConfig.class);
MyPropConfig config=context.getBean(MyPropConfig.class);
config.showPropVal();
context.close();
}
}
To know how we can do the above feature using .xml configuration, Please refer to the
beginning of the Notes where we have already discussed about it.
If we don’t want to use spring Environment, using @Value we can extract the
property file value at the time of bean created in spring container. But for that we must configure
either a PropertyPlaceholder-Configurer bean or a PropertySourcesPlaceholderConfigurer bean
along with @PropertySource annotation at the configuration class.
myPropNew.properties
This is our .property file.
Customer.java
package com.bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Customer {
@Value("${user.num}")
private String name;
@Value("${user.age}")
private Integer age;
public Customer()
{
//Default constructor as needed for Component Scan
}
public String toString()
{
return "Name::"+name+" Age::"+age;
}
}
PropertyDemoApp.java
package com.demo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import com.bean.Customer;
@Configuration
@ComponentScan(basePackages={"com.bean"})
@PropertySource("classpath:myPropNew.properties")
public class PropertyDemoApp {
@Bean
public
static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context =new
AnnotationConfigApplicationContext(PropertyDemoApp.class);
Customer cust=context.getBean(Customer.class);
System.out.println(cust.toString());
context.close();
}
}
Conditional beans
Suppose, we have to load a bean into spring container only when some condition satisfied.
Below is the example where if user name (from property file) is “Sukanya” then only Customer
bean will be created in the spring container.
Customer.java
This is our Customer bean.
MyConditional.java
package com.demo;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class MyConditional implements Condition{
@Override
public boolean matches(ConditionContext arg0, AnnotatedTypeMetadata arg1) {
if("Sukanya".equalsIgnoreCase(arg0.getEnvironment().getProperty("user.num")))
{
return true;
}
return false;
}
}
This is condition checking class which implements spring context Condition class “matches”
method.
Using @Conditional annotation, we can apply MyConditional.java class feature of checking the
user name, to the Customer bean while it loads to the spring container.
To understand that let’s see our configuration class file.
MyPropConfig.java
package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import com.bean.Customer;
@Configuration
@PropertySource("classpath:myPropNew.properties")
public class MyPropConfig {
@Autowired
Environment env;
public void showPropVal()
{
System.out.println("User name::"+env.getProperty("user.num")+"
Age::"+env.getProperty("user.age"));
}
@Bean
@Conditional(MyConditional.class)
public Customer getCustomer()
{
return new
Customer(env.getProperty("user.num"),env.getProperty("user.age",Integer.class));
}
}
myPropNew.properties
This is our property file from where user.num key is defined as user
name. By using spring Environment, we are fetching the values from the .properties file.
PropertyDemoApp.java
package com.demo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.bean.Customer;
public class PropertyDemoApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =new
AnnotationConfigApplicationContext(MyPropConfig.class);
try
{
Customer cust=context.getBean(Customer.class);
System.out.println(cust.toString());
}catch(Exception exp)
{
System.out.println("Customer is not Lucky:::"+exp.getMessage());
}
context.close();
}
}
OUTPUT:- Customer is not Lucky:::No qualifying bean of type [com.bean.Customer] is
defined
Because, in property file user name is not Sukanya, its Sara. So Customer bean is not created
in the spring container and No qualifying bean Exception comes.
Scoping beans
By default, all beans created in the spring application context are created as singletons.
Spring defines several scopes under which a bean can be created, including the following:
Singleton—one instance of the bean is created for the entire application.
Prototype—one instance of the bean is created every time the bean is injected
into or retrieved from the Spring application context.
Example:-
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Notepad notepad() {
return new Notepad();
}
configuring the bean in XML, you can set the scope using the scope attribute of the
<bean> element:
<bean id="notepad"
class="com.myapp.Notepad"
scope="prototype" />
Regardless of how you specify prototype scope, an instance of the bean will be created
each and every time it’s injected into or retrieved from the spring application context.
Consequently, everyone gets their own instance of Notepad.
Session—in a web application, one instance of the bean is created for each session.
Request—in a web application, one instance of the bean is created for each request.
For the last two scoping of bean, we cannot create full project on that now. Just understand the
theory here and the syntax so that we could tell something in case this question is asked by the
interviewer.
Syntax:-
@Component
@Scope(
value=WebApplicationContext.SCOPE_SESSION,
proxyMode=ScopedProxyMode.INTERFACES)
public ShoppingCart cart() { ... }
XML
To set the proxy mode, you must use a new element from Spring’s aop namespace:
<bean id="cart"
class="com.myapp.ShoppingCart"
scope="session">
<aop:scoped-proxy />
</bean>
<aop:scoped-proxy> is the Spring XML configuration’s counterpart to the @Scope annotation’s
proxyMode attribute. It tells Spring to create a scoped proxy for the bean. By default, it uses
CGLib to create a target class proxy.
But you can ask it to generate an interface-based proxy by setting the proxy-target-class
attribute to false:
<bean id="cart"
class="com.myapp.ShoppingCart"
scope="session">
<aop:scoped-proxy proxy-target-class="false" />
</bean>
In order to use the <aop:scoped-proxy> element, you must declare Spring’s aop
namespace in your XML configuration:
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
...
</beans>
Syntax Meaning
This tells Spring to create an instance of the ShoppingCart bean for each session in a web
application. There will be multiple instances of the ShoppingCart bean, but only one will be
created for a given session and it will essentially be a singleton as far as that session is
concerned.
Scenario:-
Suppose you want to inject the ShoppingCart bean into the following setter
method on a singleton StoreService bean:
@Component
public class StoreService {
@Autowired
public void setShoppingCart(ShoppingCart shoppingCart) {
this.shoppingCart = shoppingCart;
}
...
}
Problem:-
Because StoreService is a singleton bean, it will be created as the Spring application context is
loaded. As it’s created, Spring will attempt to inject ShoppingCart into the setShoppingCart()
method. But the ShoppingCart bean, being session scoped, doesn’t exist yet. There won’t be an
instance of ShoppingCart until a user comes along and a session is created.
Moreover, there will be many instances of ShoppingCart: one per user. You don’t want Spring to
inject just any single instance of ShoppingCart into StoreService.
This proxy will expose the same methods as ShoppingCart so that for all StoreService knows, it
is the shopping cart.
Wiring with the Spring Expression Language (p-89, spring in action, great
book)
Power of SpEL
SpEL has a lot of tricks up its sleeves, including the following:
The ability to reference beans by their IDs
Invoking methods and accessing properties on objects
Mathematical, relational, and logical operations on values
Regular expression matching
Collection manipulation
SpEL can also be used for purposes other than dependency injection. Spring Security, for
example, supports defining security constraints using SpEL expressions. And if you’re using
Thymeleaf templates as the views in your Spring MVC application, those templates can use
SpEL expressions to reference model data.
Let’s design a project using SPEL. In this part, we will introduce autowiring properties through
SPEL literal and referring systemProperties key.
Driver.java
package com.bean;
public interface Driver {
void speed();
}
This is a Driver interface.
BusDriver.java
package com.bean;
import org.springframework.beans.factory.annotation.Value;
public class BusDriver implements Driver{
@Value("#{systemProperties['user.name']}")
private String name;
@Value("#{30*2}")
private Integer speed;
public BusDriver()
{
}
public void speed() {
System.out.println(name+" The bus speed should be::"+speed);
}
}
This is a BusDriver class whose name is being injected by systemProperties class object which
is fetched by SPEL and speed is injected by SPEL literal.
DemoApp.java
package com.testing;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import com.bean.BusDriver;
import com.bean.Driver;
public class DemoApp {
@Bean
public Driver getDriver()
{
return new BusDriver();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(DemoApp.class);
Driver driver=context.getBean(BusDriver.class);
driver.speed();
context.close();
}
}
OUTPUT:-
Sumit The bus speed should be::60
Here, the value Sumit is coming from system internal properties i.e. user.name which is Desktop
PC user name.
Now let’s get other bean property value and inject that to some other bean property.
For that suppose TaxiDriver class has some speed and we will take that speed value at runtime
and inject it to BusDriver class.
TaxiDriver.java
package com.bean;
public class TaxiDriver implements Driver{
private String name;
public Integer speed;
public TaxiDriver(String theName,Integer theSpeed)
{
name=theName;speed=theSpeed;
}
public void speed() {
System.out.println(name+" The Taxi speed should be::"+speed);
}
}
BusDriver.java
package com.bean;
import org.springframework.beans.factory.annotation.Value;
public class BusDriver implements Driver{
@Value("#{systemProperties['user.name']}")
private String name;
@Value("#{taxiDriver.speed}")
private Integer speed;
public BusDriver()
{
}
public void speed() {
System.out.println(name+" The bus speed should be::"+speed);
}
}
DemoApp .java
package com.testing;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import com.bean.BusDriver;
import com.bean.Driver;
import com.bean.TaxiDriver;
public class DemoApp {
@Bean
public Driver getDriver()
{
return new BusDriver();
}
@Bean(name="taxiDriver")
public Driver getTaxiDriver()
{
return new TaxiDriver("Montuk", 50);
}
public static void main(String[] args) {
AnnotationConfigApplicationContext context=new
AnnotationConfigApplicationContext(DemoApp.class);
Driver driver=context.getBean(BusDriver.class);
driver.speed();
context.close();
}
}
There is a small problem here, i.e. speed property of TaxiDriver class should be public.
Otherwise, SPEL can’t fetch the speed value while injecting speed of the BusDriver class.
SPEL has power to even call the method which can be the solution of our above problem.