Spring Dependency Injection Annotation Example, Beans Auto-wiring using @Autowired, @Qualifier & @Resource Annotations Configuration

This article shows Spring Dependency Injection Annotation example + Spring Auto-wiring Annotation example.
We will learn Spring Dependency Injection and Beans auto-wiring using Spring @Autowired annotation. @Autowired can be applied on a bean’s constructor, field, setter method or a config method to autowire the dependency using Spring’s dependency injection.

@Autowired wires the dependency using bean datatype. If you are looking for bean wiring using bean name (somewhat analogues to byName in XML), you can use standard @Resource annotation with ‘name’ attribute. @Qualifier annotation is often used in conjunction with @Autowired to resolve ambiguity in case more that one bean of injected type exist in application context. Let’s get going.

Let’s explore practical usage of each of them in detail via examples:

1. @Resource Example (autowiring by name)

Define Beans to work with

package com.websystique.spring.domain;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component("application")
public class Application {

	@Resource(name="applicationUser")
	private ApplicationUser user;

	@Override
	public String toString() {
		return "Application [user=" + user + "]";
	}
}
package com.websystique.spring.domain;

import org.springframework.stereotype.Component;

@Component("applicationUser")
public class ApplicationUser {

	private String name = "defaultName";

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "ApplicationUser [name=" + name + "]";
	}
}

Standard @Resource annotation marks a resource that is needed by the application. It is analogous to @Autowired in that both injects beans by type when no attribute provided. But with name attribute, @Resource allows you to inject a bean by it’s name, which @Autowired does not.

In above code, Application’s user property is annotated with @Resource(name=”applicationUser”). In this case, a bean with name ‘applicationUser’ found in applicationContext will be injected here.

Spring Configuration Class

package com.websystique.spring.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.websystique.spring")
public class AppConfig {

}

Notice @ComponentScan which will make Spring auto detect the annotated beans via scanning the specified package and wire them wherever needed (using @Resource or @Autowired ).

Above configuration is analogues to following in 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-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<context:component-scan base-package="com.websystique.spring" />

</beans>

Run Application

Load the context and run it.

package com.websystique.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import com.websystique.spring.config.AppConfig;
import com.websystique.spring.domain.Application;

public class AppMain {

	public static void main(String args[]){
		AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AppConfig.class);
	    
		//Byname Autowiring
		Application application = (Application)context.getBean("application");
	    System.out.println("Application Details : "+application);

	}

}

Following will be the output.

Application Details : Application [user=ApplicationUser [name=defaultName]]

2. @Autowired Example

Define Beans to work with

package com.websystique.spring.domain;

import org.springframework.stereotype.Component;

@Component
public class License {

	private String number="123456ABC";

	@Override
	public String toString() {
		return "License [number=" + number + "]";
	}
	//setters, getters
}

@Autowired on Setter method

package com.websystique.spring.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("driver")
public class Driver {

	private License license;
	
	@Autowired
	public void setLicense(License license) {
		this.license = license;
	}

	@Override
	public String toString() {
		return "Driver [license=" + license + "]";
	}
	//getter
}

@Autowired on Field

package com.websystique.spring.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("driver")
public class Driver {
	@Autowired
	private License license;
	
	//getter,setter

	@Override
	public String toString() {
		return "Driver [license=" + license + "]";
	}
}

@Autowired on Constructor

package com.websystique.spring.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("driver")
public class Driver {

	private License license;
	
	@Autowired
	public Driver(License license){
		this.license = license;
	}
	
	@Override
	public String toString() {
		return "Driver [license=" + license + "]";
	}
}

Run Application
Load the context and Run it.

package com.websystique.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import com.websystique.spring.config.AppConfig;
import com.websystique.spring.domain.Driver;

public class AppMain {

	public static void main(String args[]) {
		AbstractApplicationContext context = new AnnotationConfigApplicationContext(
				AppConfig.class);

		Driver driver = (Driver) context.getBean("driver");
		System.out.println("Driver Details : " + driver);
	}

}

Following will be the output

Driver Details : Driver [license=License [number=123456ABC]]

3. @Qualifier Example

@Qualifier is useful for the situation where you have more than one bean matching the type of dependency and thus resulting in ambiguity.

Define Beans to work with

package com.websystique.spring.domain;

public interface Car {

	public void getCarName();

}
package com.websystique.spring.domain;

import org.springframework.stereotype.Component;

@Component("Ferari")
public class Ferari implements Car{

	public void getCarName() {
		System.out.println("This is Ferari");
	}

}

package com.websystique.spring.domain;

import org.springframework.stereotype.Component;

@Component("Mustang")
public class Mustang implements Car{

	public void getCarName() {
		System.out.println("This is Mustang");
	}

}
package com.websystique.spring.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Bond {

	@Autowired
	private Car car;
	
	public void showCar(){
		car.getCarName();
	}
}

Run Applicaion

Load context and Run it.

package com.websystique.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

import com.websystique.spring.config.AppConfig;
import com.websystique.spring.domain.Bond;

public class AppMain {

	public static void main(String args[]) {
		AbstractApplicationContext context = new AnnotationConfigApplicationContext(
				AppConfig.class);

		Bond bond = (Bond) context.getBean("bond");
		bond.showCar();
	}

}

On running, Spring throws following exception:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.websystique.spring.domain.Car] is defined: expected single matching bean but found 2: Ferari,Mustang
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:970)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
	... 14 more

What happened is Spring was not able to decide which bean (Ferari or Mustang as both implements Car) to choose for auto-wiring ,it throws this exception.

Happily, @Qualifier saves the day.

Change the Bond class as shown below

package com.websystique.spring.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Bond {

	@Autowired
	@Qualifier("Mustang")
	private Car car;
	
	public void showCar(){
		car.getCarName();
	}
}

Run Application

Following will be the output.

This is Mustang

Mark Autowiring optional with attribute required=”false”

By default, @Autowored annotation makes sure that field is indeed autowired. In case autowiring is not successful, Spring will throw an exception. There are times however when you want to make autowiring optional. Setting @Autowired required attribute to ‘false’ will make this filed optional for autowiring and Spring will skip it(remain null) if dependency not found.

package com.websystique.spring.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("driver")
public class Driver {
	@Autowired(required=false)
	private License license;
	
	//getter,setter

	@Override
	public String toString() {
		return "Driver [license=" + license + "]";
	}
}

In above example, if no bean of type License been found, it will remain null and no error will be thrown on context loading.

caveat :
Note that standard @Resource annotation does not have this flexibility. In case the dependency annotated with @Resource not found, Spring will throw an exception. Both @Resource and @Autowired have few differences : No optionality in @Resource and no autowiring by bean name in @Autowired.
All in all, @Autowired is the most widely used option compare to @Resource and autowire attribute in XML.

That’s it.

Download Source Code


References