If you read my post about the @Qualifier
annotation, you have noticed that defining two beans of the same type can be a challenge. By distinguishing it with a qualifier name, @Qualifier
helps Spring determine which bean to inject.
The @Primary
annotation will help Spring decide which of those same types of beans it should pick primarily.
For the bean annotated with the @Primary
annotation, the @Qualifier
will not be necessary. It is only required for the other bean.
Example 1: Using @Primary and @Qualifier in Spring
Let’s see the example in practice:
public interface GreetingService {
String greet();
}
@Service
@Primary
public class EnglishGreetingService implements GreetingService {
@Override
public String greet() {
return "Hello!";
}
}
@Service("spanishGreetingService")
public class SpanishGreetingService implements GreetingService {
@Override
public String greet() {
return "Hola!";
}
}
@RestController
@RequestMapping("/greet")
public class GreetingController {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GreetingController.class);
@Autowired
private GreetingService greetingService;
@Autowired
@Qualifier("spanishGreetingService")
private GreetingService spanishGreetingService;
@GetMapping
public ResponseEntity<String> printGreetings() {
log.info(greetingService.greet());
log.info(spanishGreetingService.greet());
return ResponseEntity.ok("greetings");
}
}
You won’t need to use the @Qualifier
on the bean you defined as @Primary
When you call this controller with this curl:
curl <http://localhost:8080/greet>
You are going to see in the logs that the primary one was automatically set:
2024-06-20T21:08:53.884-03:00 INFO 1868 --- [nio-8080-exec-1] c.s.mastery.primary.GreetingController : Hello!
2024-06-20T21:08:53.884-03:00 INFO 1868 --- [nio-8080-exec-1] c.s.mastery.primary.GreetingController : Hola!
Example 2: Using @Primary at the Configuration Level
Another example is when you need to use the bean at the configuration level, so it will not be possible to use the @Qualifier
to identify which bean Spring should inject.
@Configuration
public class AppPrimaryConfig {
@Bean
@Primary
public ConfigGreetingService portugueseGreetings() {
return new PortugueseGreetings();
}
@Bean("italianGreetings")
public ConfigGreetingService italianGreetings() {
return new ItalianGreetings();
}
}
@RestController
@RequestMapping("/new-greetings")
public class NewGreetingController {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(GreetingController.class);
@Autowired
private ConfigGreetingService greetingService;
@Autowired
@Qualifier("italianGreetings")
private ConfigGreetingService italianGreetings;
@GetMapping
public ResponseEntity<String> printGreetings() {
log.info(greetingService.greet());
log.info(italianGreetings.greet());
return ResponseEntity.ok("greetings");
}
}
When you call the controller:
curl <http://localhost:8080/new-greetings>
You should see:
2024-06-20T21:10:17.517-03:00 INFO 8768 --- [nio-8080-exec-1] c.s.mastery.primary.GreetingController : Ola
2024-06-20T21:10:17.517-03:00 INFO 8768 --- [nio-8080-exec-1] c.s.mastery.primary.GreetingController : Ciao
Conclusion
In this blog post, you learned about the @Primary
annotation and its use cases.
If you like this topic, make sure to follow me. In the following days, I’ll be explaining more about Spring annotations! Stay tuned!