Spring @Autowired Annotation Example
Spring autowiring using @Autowired
annotation will inject dependent beans automatically. In the last tutorial, we have learned autowiring through the XML configuration metadata. @Autowired
annotation internally uses the byType mechanism and no need to apply autowire attribute.
We can apply @Autowired
annotation on the followings.
- @Autowired on field
- @Autowired on setter method
- @Autowired on constructor
Before using @Autowired
annotation, we need to activate it. It can be done by two ways.
1- Add the context namespace schema to the root tag <bean/>
and include <context:annotation-config />
.
<beans
//...
xmlns:context="http://www.springframework.org/schema/context"
//...
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config />
</beans>
2- Or create the object of class AutowiredAnnotationBeanPostProcessor
.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>
I recommend, must go with context namespace, because it will activate all the annotation beans. And if go with second option it will activate only @Autowired
annotation which is not suitable for the large project.
Note: Autowiring functionality allows you to inject only secondary type’s value, it is not applicable for primitive type’s value. Primitive types value must be inject manually.
Let’s see the complete example one by one.
1. @Autowired on fields
In this example, we have applied @Autowired
annotation on the secondary type dependents property.
If you apply
@Autowired
on the property name or fields, there is no need to create setter methods or constructor.
1.1 Spring Beans
Create the two beans classes and instantiate the first one into the second one.
package org.websparrow.beans.field;
public class State {
// Generate setters and getters...
private String stateName;
}
package org.websparrow.beans.field;
import org.springframework.beans.factory.annotation.Autowired;
public class Country {
@Autowired
private State state;
public void display() {
System.out.println("State name is: " + state.getStateName());
}
}
1.2 Spring Beans Configuration
Configure the bean’s classes into the XML configuration file.
<?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">
<context:annotation-config />
<bean id="s1" class="org.websparrow.beans.field.State">
<property name="stateName" value="Uttar Pradesh" />
</bean>
<bean id="country" class="org.websparrow.beans.field.Country" />
</beans>
1.3 Run it
Load configuration file into IoC container and run it.
package org.websparrow.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.beans.field.Country;
public class Test1 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-field.xml");
Country c = (Country) context.getBean("country");
c.display();
}
}
1.4 Output
You will the following result on your console log.
State name is: Uttar Pradesh
2. @Autowired on setters method
You can also apply @Autowired
annotation on the setter methods of secondary type dependent beans for automatic dependency injection.
2.1 Spring Beans
To demonstrate, I have used the above both beans and apply the annotation on the setter method.
package org.websparrow.beans.setter;
public class State {
// Generate setters and getters...
private String stateName;
}
package org.websparrow.beans.setter;
import org.springframework.beans.factory.annotation.Autowired;
public class Country {
private State state;
@Autowired
public void setState(State state) {
this.state = state;
}
public void display() {
System.out.println("State name is: " + state.getStateName());
}
}
2.2 Spring Beans Configuration
Spring beans configuration file is almost the same, only the minor changes in the package name.
<?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">
<context:annotation-config />
<bean id="s4" class="org.websparrow.beans.setter.State">
<property name="stateName" value="Bihar" />
</bean>
<bean id="c" class="org.websparrow.beans.setter.Country" />
</beans>
2.3 Run it
To test it, load the spring-setter.xml configuration file and run it.
package org.websparrow.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.beans.setter.Country;
public class Test2 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-setter.xml");
Country c = (Country) context.getBean("c");
c.display();
}
}
2.4 Output
You will get the desired result on your console log.
State name is: Bihar
Remember: Autowiring functionality allows you to inject only secondary type’s value, it is not applicable for primitive type’s value. Primitive types value must be inject manually.
3. @Autowired on constructors
@Autowired
annotation is also applicable for the constructor. Apply it on the top of those parameterized constructors where you have used the secondary type values.
3.1 Spring Beans
Create the two beans classes and a secondary type parameterized constructor.
package org.websparrow.beans.constructor;
public class State {
// Generate setters and getters...
private String stateName;
}
package org.websparrow.beans.constructor;
import org.springframework.beans.factory.annotation.Autowired;
public class City {
private State state;
@Autowired
public City(State state) {
this.state = state;
}
public void print() {
System.out.println("Varanasi is a city in " + state.getStateName() + " state.");
}
}
3.2 Spring Beans Configuration
Beans configuration file is similar to all above.
<?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">
<context:annotation-config />
<bean id="s1" class="org.websparrow.beans.constructor.State">
<property name="stateName" value="Uttar Pradesh" />
</bean>
<bean id="city" class="org.websparrow.beans.constructor.City" />
</beans>
3.3 Run it
Load the configuration file and run it.
package org.websparrow.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.beans.constructor.City;
public class Test3 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-constructor.xml");
City c = (City) context.getBean("city");
c.print();
}
}
3.4 Output
You will the following output on your console log.
Varanasi is a city in Uttar Pradesh state.
All the above example works fine but sometimes you may face the problem of ambiguity. Because we know that @Autowired
annotation internally uses the byType mechanism. If it finds more than one eligible beans, it will throw the exception.
See the below configuration file. It has two eligible beans.
<bean id="s1" class="org.websparrow.beans.constructor.State">
<property name="stateName" value="Uttar Pradesh" />
</bean>
<bean id="s2" class="org.websparrow.beans.constructor.State">
<property name="stateName" value="Delhi" />
</bean>
<bean id="city" class="org.websparrow.beans.constructor.City" />
So Spring container unable to identify which beans should I inject and throw these exceptions.
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'city' defined in class path resource [spring-constructor.xml]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.websparrow.beans.constructor.State' available: expected single matching bean but found 2: s1,s2
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:729)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:192)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1270)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.websparrow.beans.constructor.State' available: expected single matching bean but found 2: s1,s2
at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:215)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1113)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1062)
To resolve the ambiguity problem, Spring framework will provide one more attribute of <bean/>
element i.e. autowire-candidate
. By default, its value is true. If you changed its value false, it will not allow the bean to participate in autowiring or we can use the @Qualifier
annotation discussed in the next tutorial.
Download Source Code: spring-autowired-annotation-example