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.

  1. @Autowired on field
  2. @Autowired on setter method
  3. @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 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 second one.

State.java
package org.websparrow.beans.field;

public class State {

	// Generate setters and getters...
	private String stateName;

}
Country.java
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 beans classes into the XML configuration file.

spring-field.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">

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

Test1.java
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.

State.java
package org.websparrow.beans.setter;

public class State {

	// Generate setters and getters...
	private String stateName;

}
Country.java
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 same, only the minor changes in the package name.

spring-setter.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">

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

Test2.java
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 constructor. Apply it on the top of those parameterized constructor where you have used the secondary type values.

3.1 Spring Beans

Create the two beans classes and a secondary type parameterized constructor.

State.java
package org.websparrow.beans.constructor;

public class State {

	// Generate setters and getters...
	private String stateName;

}
City.java
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.

spring-constructor.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">

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

Test3.java
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 some time 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 have 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 identity which beans should I inject and throw these exception.

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 next tutorial.


Share this article on: