@Autowired in SpringBoot

  • Spring @Autowired annotation is used for automatic dependency injection.
  • Once we create a bean by using @Component annotation we can use that bean in any of the other set of beans, and we do that by using @Autowired annotation above the reference of the class inside a nested bean.
  • By using @Autowired annotation we are doing automatic dependency injection to a reference of a class.

There are different ways through which we can autowire a spring bean.

  1. autowire byType – For this type of autowiring, class type is used. So there should be only one bean configured for this type in the spring bean configuration file.
  2. autowire by constructor – This is almost similar to autowire byType, the only difference is that constructor is used to inject the dependency.
  3. autowire byName – For this type of autowiring, setter method is used for dependency injection. Also the variable name should be same in the class where we will inject the dependency and in the spring bean configuration file.
  4. autowire by autodetect – If you are on Spring 3.0 or older versions, this is one of the autowire options available. This option was used for autowire by constructor or byType, as determined by Spring container. Since we already have so many options, this option is deprecated. I will not cover this option in this tutorial.
  5. @Autowired annotation – We can use Spring @Autowired annotation for spring bean autowiring. @Autowired annotation can be applied on variables and methods for autowiring byType. We can also use @Autowired annotation on constructor for constructor based spring autowiring.For @Autowired annotation to work, we also need to enable annotation based configuration in spring bean configuration file. This can be done by context:annotation-config element or by defining a bean of type org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.
  6. @Qualifier annotation – This annotation is used to avoid conflicts in bean mapping and we need to provide the bean name that will be used for autowiring. This way we can avoid issues where multiple beans are defined for same type. This annotation usually works with the @Autowired annotation. For constructors with multiple arguments, we can use this annotation with the argument names in the method.

Autowired by Type

  • This type of Autowire happens when you put the annotation @Autowired before a Reference of a class or on a setter method which takes Object reference as a parameter of that setter

We will autowire an Animal class object into a Forest Class in below example :

package GradleDemo;

import org.springframework.stereotype.Component;

@Component
public class Animal {
	String name="Hello Forest....This is an animal";

	public String getName() {
		return name;
	}

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

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

@Component
public class Forest {
	@Autowired
	Animal animal;

	public Animal getAnimal() {
		return animal;
	}

	//@Autowired - This will also pass a new variable in setAnimal method call
	public void setAnimal(Animal animal) {
		this.animal = animal;
	}
	
}

The main class will looks something like this :

package GradleDemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        ApplicationContext applicationContext = SpringApplication.run(App.class, args);
        Forest forest = applicationContext.getBean(Forest.class);
        System.out.println(forest.getAnimal().getName());
    }

}

build.gradle

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.0.5.RELEASE'
    id 'io.spring.dependency-management' version '1.0.7.RELEASE'
}

repositories {
    jcenter()
}

dependencies {
    implementation 'com.google.guava:guava:28.0-jre'
    testImplementation 'junit:junit:4.12'
    implementation 'org.springframework.boot:spring-boot-dependencies:2.0.5.RELEASE'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

    components {
        withModule('org.springframework:spring-beans') {
            allVariants {
                withDependencyConstraints {
                    it.findAll { it.name == 'snakeyaml' }.each { it.version { strictly '1.19' } }
                }
            }
        }
    }
}

bootJar {
    mainClassName = 'GradleDemo.App'
}

task runJar{
	dependsOn 'assemble'
	dependsOn 'jar'
	doLast{
  		javaexec { 
    		main="-jar";
    		args = [
            	"build/libs/"+rootProject.name+".jar"
           	]
		} 
	}
}

Autowire by Constructor using @Qualifier

  • The use of @Qualifier is to fix that the bean with a given name will only qualify for dependency injection in autowiring
  • In the scenario where more than one bean is eligible to be autowired, we can use @Qualifier annotation.
  • The same scenario can also be handled by @Primary annotation but @Qualifier defines more robust selection criteria than @Primary annotation.

Example : In this example we have created an Interface named LivingCreature and this interface is implemented into two classes name Animals and Fish. Now when LivingCreature interface reference is autowired which class’s Object will be created Animals class or Fish class? There will be a conflict for SpringBoot on this hence to resolve this conflict we use @Qualifier in the below example to point to the exactly which class’s object has to be created

public interface LivingCreature {
	public String getName();
}
@Component(value="animal")
public class Animal implements LivingCreature{

	String name="Hello Forest....This is an animal";
	
	@Override
	public String getName() {
		return name;
	}
}
@Component(value="fish")
public class Fish implements LivingCreature{
	
	String name="Hello Forest....This is an fish";

	@Override
	public String getName() {
		return name;
	}
}
@Component
public class Forest {
	@Autowired
	@Qualifier("Animal")
	LivingCreature livingCreature;	
}

Leave a Comment