Sei sulla pagina 1di 54

Stick to the book(Spring in Action, 4th Edition) 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

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.

This is our project set up.

Step 1:- Creating our Bean

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);
}
}

This is our bean which will be loaded into spring container.


Step 2:- Configuring Spring Beans

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" />
</beans>

This is the xml config file where ApplicationContext will search for the beans.

Step 3:- Creating Spring Container

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

1) Create and Manage objects i.e. Inversion of Control

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

2) Inject object’s dependencies i.e. Dependency Injection

In the above example, we just covered the Inversion of Control using xml.

Inversion of Control using JAVA annotation configuration (modern technique):-


We don’t need any xml configuration. This is going to be stand alone JAVA annotation based
configuration to achieve Inversion of Control feature of spring framework.

This is our project set up.

Step 1:- Creating our Bean

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();
}
}

This is done using @Bean and @Configuration annotation.

Step 3:- Creating 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
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();
}
}

This is done using AnnotationConfigApplicationContext as spring container.


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

Loading two different car objects

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.

Here, we have created the MyEngine.

There are two ways to inject MyEngine into the MotorCar.

Constructor Injection: (via xml)

Step 1:- Creating our Bean

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);
}
}

This is our beans and MotorCar has MyEngine.


Step 2:- Configuring Spring Beans

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>

xml config done using <constructor-arg>

Step 3:- Creating Spring Container

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();
}
}

It is unchanged same as previous project.


Constructor Injection: (via JAVA annotation)

This is our project set up.

Step 1:- Creating our Bean

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);
}
}

This is our beans and MotorCar has MyEngine.


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;
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();
}
}

JAVA annotation config done using @Bean and @Configuration annotation.


Step 3:- Creating 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;
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();
}
}

Using spring container AnnotationConfigApplicationContext.


Setter Injection: (via xml)

Step 1:- Creating our Bean

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);
}
}

This is our beans and MotorCar has MyEngine.

Step 2:- Configuring Spring Beans

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>

Using <property> for setter injection.


Step 3:- Creating Spring Container

CarDemoApp.java
Using spring container ClassPathXmlApplicationContext.

Setter Injection: (via JAVA annotation)

Let’s separate our configurations from CarDemoApp.java application file.

This is our project set up. MyCarFactory will produce Car.

Step 1:- Creating our Bean

MotorCar.java MyEngine.java
This is our beans and MotorCar has MyEngine.

Step 2:- Configuring Spring Beans

MyCarFactory.java
JAVA annotation config done using @Bean and @Configuration annotation.

Step 3:- Creating Spring Container

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.

This is our project set up.

Step 1:- Creating our Bean

MyEngine.java MotorCar.java
This is our beans and MotorCar has MyEngine.

Step 2:- Configuring Spring Beans

mySpring-config.xml
Using <property> for setter injection.

Step 3:- Creating the property file

carFeature.properties

Step 4:- Creating Spring Container

CarDemoApp.java
Using spring container ClassPathXmlApplicationContext.

Injection from Property File (via JAVA)

To understand this we need to first understand the @Autowired annotation.

Hence, let’s discuss it later.


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

Page:-34(Spring Manning book)

Automatically wiring beans


Component scanning—Spring automatically discovers beans to be created in the application context.
Autowiring—Spring automatically satisfies bean dependencies.

What is the need for?

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.

This is our project set up.

HexaCar.java AltoCar.java Car.java


Here, Car is an interface and HexaCar,AltoCar are implementation
of Car. AltoCar does not define @Component annotation.

Exception:::No bean named 'altoCar' is defined

RunDemoApp.java
HexaCar bean loaded as it defines with @Component annotation.
Introducing multiple basePackages in application config file.

This is our project set up.

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.

Annotating beans to be automatically wired


We need three annotations.

@Autowired , @Component for autowiring member beans and to create beans into spring
container.

@ComponentScan for automatically scans for the beans into packages.

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.

When required is false?


If there are no matching beans, spring will throw an exception as the application context is being
created. To avoid that exception, you can set the required attribute on @Autowired to false:
When required is false, spring will attempt to perform autowiring; but if there are no matching
beans, it will leave the bean unwired. You should be careful setting required to false, however.
Leaving the property unwired could lead to NullPointer-Exceptions if you don’t check for null in
your code.

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.

The simplest possible Spring XML configuration looks like this:


<?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">

<! -- configuration details go here -->

</beans>

Declaring a simple <bean>


To declare a bean in Spring’s XML-based configuration, you’re going to use another element
from the spring-beans schema: the <bean> element. The <bean> element is the XML analogue
to JavaConfig’s @Bean annotation.
This is a simple project set up to understand the XML based configuration.

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”.

However, we should use id for a

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.

refers to a real class?


even if it does refer to an actual type, what will happen if you rename the class?

There is no way to verify the program sysntax in xml.

Initializing a bean with constructor injection


With specific regard to constructor injection, you have two basic options to choose from:
The <constructor-arg> element
Using the c-namespace introduced in Spring 3.0
The difference between these two choices is largely one of verbosity. As you’ll see, the
<constructor-arg> element is generally more verbose than using the c-namespace and results in
XML that is more difficult to read. On the other hand, <constructorarg> can do a few things that
the c-namespace can’t.

INJECTING CONSTRUCTORS WITH BEAN REFERENCES

<bean id="myStudent" class='com.bean.Student'>


<constructor-arg ref="myName" />
</bean>

<bean id=myName class='com.bean.Name'></bean>

We already know the above syntax.

INJECTING CONSTRUCTORS WITH C-namespace

To enable our xml configuration with c-namespace feature, we need the below extra schema
definition.
xmlns:c="http://www.springframework.org/schema/c"

Example1 with reference bean and c-namespace

Red and bold are new definition regarding 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:add-ref='stuAdd'/>
<bean id='stuAdd' class='com.bean.Address'/>
</beans>

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());
}
}

The above is a small project to demonstrate c-namespace in spring.

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>

This is also possible


<bean id="myStudent" class='com.bean.Student' c:_0-ref='stuAdd'/> == indicating 0th
argument.
INJECTING CONSTRUCTORS WITH LITERAL VALUES

Injecting literal through <constructor-arg>

<?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>

Spring does a very smart thing here, i.e.


Here, the age is Integer type in JAVA, but from XML, when it passes, it automatically
converts from String literal to Integer.

Inside <constructor-arg>, class=’’ is not allowed and we don’t need to mention,


spring does it for us.

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

<?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"/>
</beans>

Even the below syntax is also allowed.


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:_0="Sumit"
c:_1="19"/>
</beans>
Even the below syntax is also allowed (mixing)
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:_0="Sumit"
c:theAge="19"/>
</beans>

So, in the case of c-namespace also spring does the automatic type conversion from String to
int for ‘theAge’ parameter here.

Suppose, we want to inject an Address bean reference through constructor.


With <constructor-arg>
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'/>
<constructor-arg ref='theAddr'/>
</bean>
<bean name='theAddr' class='com.bean.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,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

Let’s examine how property injection works in Spring XML.


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'>
<property name='name' value='Sumit'/>
<property name='age' value='30'/>
</bean>
</beans>
Student.java
package com.bean;
public class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}

public String toString()


{
return ("Name: "+name+" Age: "+age);
}
}

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>

CHOOSING BETWEEN CONSTRUCTOR INJECTION AND PROPERTY


INJECTION
General rule, we favor constructor injection for hard dependencies and property injection for any
optional dependencies.
Now, Student doesn’t have any constructor, it also doesn’t have any hard dependency.

So Can we do like below?


<bean id="myStudent" class='com.bean.Student'/>
Spring will have absolutely no problem creating that bean. Our CollegeApp would
fail with a NullPointerException.

Is setName(String name) and setAge(int age) is mandatory?


Yes. If we have <property> tag in xml then Setter method is always mandatory, otherwise spring
will not be able to find by which it will inject the property.
Alternatively, we can also use @Autowired with setter() or any arbitrary method. But, we need
one method always which will inject the properties.

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.

Property injection through p-namespace in spring

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.

Collection literal setter injection


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='subjects'>
<list>
<value>English</value>
<value>Math</value>
</list>
</property>
</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 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.

Collection objects setter injection

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.

To implement util-namespace in spring, we need below schema definitions in our xml.


xmlns:util="http://www.springframework.org/schema/util"

And we need the below xsd.


xsi:schemaLocation="http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd"

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.

util-namespace is also combinely used for injecting constructor 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"
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' c:theName='Sumit' c:theAge='27'
c:theSubjects-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 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);
}
}

CollegeApp.java
This remains unchanged.

Importing and mixing configurations

Importing multiple configuration class into one configuration class


Suppose, we have a new requirement here. To configure Address and Student, we have to
design separate configuration class and from CollegeApp, it should be able to fetch all of
them.
Here, we made Address as @Autowired.

This is our project set up.

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.

Let’s look at our Testing CollegeApp below.


package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import com.bean.Student;
@Configuration
@Import({AddressAppConfig.class,StudentAppConfig.class})
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();
}
}
Suppose, we want to load our Address configuration 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='address' class='com.bean.Address' c:theStreet='Residential
Address'></bean>
</beans>

Now, no need of AddressAppConfig.


CollegeApp.java
package com.myTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;
import com.bean.Student;
@Configuration
@Import({StudentAppConfig.class})
@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();
}
}

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>

Now, no need of AddressAppConfig and StudentAppConfig.

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.

Just a quick important recap session


Suppose, we want to automate all the things above. Then we need @Component for declaring
class as spring bean and and @ComponentScan for auto scanning of packages where spring
will scan for the spring beans.

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.

This is enough to run our application.


But, see the below output.
Name:null Age:0 null

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();
}
}

We want Elgin street to be autowired with Student address.


Address.java
package com.bean;
import org.springframework.stereotype.Component;
@Component
public class Address {
private String street;
public Address()
{
}
public Address(String theStreet)
{
street=theStreet;
}
public String toString()
{
return (" Address:"+street);
}
}
Student.java
package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Student {
private String name;
private int age;
private Address address;
public Student()
{
}
public Student(String theName,int theAge)
{
name=theName;age=theAge;
}
@Autowired
public void setAddress(Address address) {
this.address = address;
}
public String toString()
{
return ("Name:"+name+" Age:"+age+ " "+address);
}
}

Output: - Name:null Age:0 Address:null //Address not Autowired here.

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.

Vehicle.java MotorBike.java ByCycle.java


Where vehicle is an Interface and ByCycle, MotorBike are the implementation of Vehicle
interface.
Now, consider the following situation where Autowiring has multiple implementation beans in
spring container and which one to choose?
Student.java
package com.bean;
import org.springframework.beans.factory.annotation.Autowired;
public class Student {
private String name;
private int age;
@Autowired
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
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();
}
}

Runtime Exception: org.springframework.beans.factory.NoUniqueBeanDefinitionException:

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();
}
}

Additional topic:- https://www.baeldung.com/spring-autowire(section:5.2)


Is for @Autowired by custom qualifier.

Injecting External Values


Spring Environment
Retrieve the properties via the and
@PropertySource is the simplest and shortest way to retrieve values from an external property
file.
myPropNew.properties
This is our .properties file from where spring will pick up the values at
runtime through the key.
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("file:E:/Common_WorkSpace270618/SpringProperty1208/src/myPropNew.prop
erties")
public class MyPropConfig {
@Autowired
Environment env;
public void showPropVal()
{
System.out.println("User name::"+env.getProperty("user.num")+"
Age::"+env.getProperty("user.age"));
}
}

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();
}
}

OUTPUT: - User name::Sara Age::30

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.

WHY @Value introduced?


Ans. When we declare a class as @Component and loading the bean at @ComponentScan
Then we don’t have any other option other than using @Value and configure
PropertySourcesPlaceholderConfigurer bean.

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();
}

We can also use @Scope("prototype")

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.

As configured, proxyMode is set to ScopedProxyMode.INTERFACES, indicating that the proxy


should implement the ShoppingCart interface and delegate to the implementation bean. This is
fine (and the most ideal proxy mode) as long as ShoppingCart is an interface and not a class.

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.

Problem Resolution: - (See Syntax)


Instead of injecting the actual ShoppingCart bean into StoreService, Spring should inject a
proxy to the ShoppingCart bean.

This proxy will expose the same methods as ShoppingCart so that for all StoreService knows, it
is the shopping cart.

But when StoreService calls methods on ShoppingCart, the


proxy will lazily resolve it and delegate the call to the actual session-scoped Shopping-
Cart bean.

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.

This is out project set up.

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.

Here systemProperties belongs to “java.util.Properties” which mainly contains the internal


system properties. But, don’t get it wrong that this can be configured to get classpath property
file values.

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.

Potrebbero piacerti anche