Understanding @Primary in Spring
Tags: java, springboot, spring, programming
Published: 2024-06-21 00:21:57

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:

```java
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:

```bash
curl http://localhost:8080/greet
```

You are going to see in the logs that the primary one was automatically set:

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

```java
@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:

```bash
curl http://localhost:8080/new-greetings
```

You should see:

```bash
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!

Follow me!