@Primary in Spring

0
1671

In this tutorial, we will discuss on Spring’s @Primary annotation with examples, @Primary is available in Spring Framework since 3.0 version.

1. @Primary annotation in Spring

When there are multiple beans available of same type in Spring container, all of them are qualified to be autowired to single-valued dependency. That causes ambiguity and leads to throw an exception by framework. @Primary indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency.

There should be only one @Primary bean among same type of beans.

Let’s see an example.

package com.javabydeveloper.spring.primary;

public class Animal {

	private String name;

	public Animal(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return name;
	}
}
@Configuration
@ComponentScan("com.javabydeveloper.spring.primary")
public class AppConfigForPrimary {
	
	@Bean
	public Animal tigerBean() {
		return new Animal("Tiger");
	}
	
	@Bean
	@Primary
	public Animal kangarooBean() {
		return new Animal("Kangaroo");
	}
	
	@Bean
	public Animal foxBean() {
		return new Animal("Fox");
	}

	// ... Other beans
}
package com.javabydeveloper.spring.primary;
// ...
public class PrimaryDITestBean {

	@Autowired
	private Animal animal;

	public void printAnimal() {
		System.out.println(animal);
	}

	// ...
}

Testing :

public class ApplicationPrimaryDemo {

	public static void main(String[] args) {
		ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForPrimary.class);

		PrimaryDITestBean pdits = ctxt.getBean(PrimaryDITestBean.class);
		pdits.printAnimal();
                // ...
	}
}

Output :

Kangaroo
//...

2. Using @Primary with @Component

In previous example we have seen how to use @Primary with @Bean. @Primary may be used on any class directly or indirectly annotated with @Component class.

Let’s see an example.

package com.javabydeveloper.spring.primary;

public interface DataService {

	public void printData();
}
package com.javabydeveloper.spring.primary;
// ...

@Component
public class BinaryDataService implements DataService {

	@Override
	public void printData() {
		System.out.println("Binary Data");
	}
}
package com.javabydeveloper.spring.primary;
// ...

@Component
@Primary
public class TextDataService implements DataService {

	@Override
	public void printData() {
		System.out.println("Text Data");
	}
}
public class PrimaryDITestBean {

	// ...

	@Autowired
	private DataService dataService;

	public void printData() {
		dataService.printData();
	}

	// ...
}

Testing :

public class ApplicationPrimaryDemo {

	public static void main(String[] args) {
		ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForPrimary.class);

		PrimaryDITestBean pdits = ctxt.getBean(PrimaryDITestBean.class);
		pdits.printData();
                // ...
	}
}

Output :

Text Data
//...

3. Spring @Primary vs @Qualifier

3.1. We use @Qualifier in Spring to autowire a specific bean among same type of beans, where as @Primary is used to give high preference to the specific bean among multiple beans of same type to inject to a bean.

3.2. Suppose that you have provided multiple beans of same type and Spring is responsible to autowire a bean for that type (example: multiple datasources in single application), you need to tell Spring which bean should get autowired by default by annotating bean with @Primary, and we can not use @Qualifier in that situation because Spring will lookup for dependency in configuration phase.

3.3. We can use @Qualifier and @Primary for the same bean. Use @Qualifier to inject specific bean otherwise Spring injects bean by default which is annotated with @Primary.

Let’s see an example.

package com.javabydeveloper.spring.primary;

public interface Bird {

}
package com.javabydeveloper.spring.primary;

public class Eagle implements Bird {

	@Override
	public String toString() {
		return "Eagle";
	}
}
public class Peacock implements Bird{

	@Override
	public String toString() {
		return "Peacock";
	}
}
@Configuration
@ComponentScan("com.javabydeveloper.spring.primary")
public class AppConfigForPrimary {
	// ...

	@Bean
	@Primary
	@Qualifier("peacockBean")
	public Bird peacock() {
		return new Peacock();
	}
	
	@Bean
	@Qualifier("eagleBean")
	public Bird eagle() {
		return new Eagle();
	}

}
public class PrimaryDITestBean {

	@Autowired
	@Qualifier("eagleBean")
	private Bird bird;

	// ...

	public void printBird() {
		System.out.println(bird);
	}
}

Testing :

public class ApplicationPrimaryDemo {

	public static void main(String[] args) {
		ApplicationContext ctxt = new AnnotationConfigApplicationContext(AppConfigForPrimary.class);

		PrimaryDITestBean pdits = ctxt.getBean(PrimaryDITestBean.class);
		pdits.printBird();

		// ...
	}
}

Output :

Eagle
// ...

Comment line @Qualifier("eagleBean") in PrimaryDITestBean class and test again.

Output :

Peacock
// ...

4. Conclusion

In this quick tutorial we have seen how to use Spring’s @Primary annotation in Spring applications with examples.

You can get source code from our GitHub repository.

5. References

  1. Spring Reference Document
  2. Spring Java Document

Other Related Tutorials:

  1. Spring @Autowired
  2. Spring @Lazy
  3. Spring Boot XML Configuration
  4. Spring Injecting Collection
  5. Spring @Order
  6. Spring @Import
  7. Spring Component Scanning
  8. Spring @ComponentScan Filter Types

LEAVE A REPLY

Please enter your comment!
Please enter your name here