19‐Annotation Autowiring and Qualifiers - JulianeMaran32/Java-with-Spring-Boot GitHub Wiki
@Qualifier
) – Visão Geral
44. Qualificadores (Autowiring (Injeção Automática)
- Quando usamos injeção automática no Spring, ele tenta encontrar e injetar automaticamente um componente (
@Component
) que implemente uma determinada interface. - Se houver apenas uma implementação da interface, tudo funciona bem.
- Mas... e se existirem várias implementações?
Exemplo com Múltiplos "Coach" (Treinadores)
Digamos que temos a interface Coach
, e várias classes que a implementam:
@Component
public class CricketCoach implements Coach {
public String getDailyWorkout() {
return "Treine arremesso rápido por 15 minutos";
}
}
@Component
public class TrackCoach implements Coach {
public String getDailyWorkout() {
return "Corra uma prova intensa de 5km!";
}
}
@Component
public class BaseballCoach implements Coach {
public String getDailyWorkout() {
return "Pratique rebatidas por 30 minutos";
}
}
@Component
public class TennisCoach implements Coach {
public String getDailyWorkout() {
return "Treine seu voleio de backhand";
}
}
Problema: Múltiplas Implementações Encontradas
Se você tentar injetar um Coach
assim:
private Coach myCoach;
O Spring não saberá qual classe usar, porque há quatro opções. O erro será algo como:
Erro: o construtor precisa de um único bean, mas foram encontrados 4:
- baseballCoach
- cricketCoach
- tennisCoach
- trackCoach
@Qualifier
para Especificar
Solução: Use Para resolver esse problema, usamos a anotação @Qualifier
, que diz ao Spring exatamente qual bean usar.
Exemplo com injeção via construtor:
@RestController
public class DemoController {
private Coach myCoach;
@Autowired
public DemoController(@Qualifier("cricketCoach") Coach myCoach) {
this.myCoach = myCoach;
}
@GetMapping("/dailyworkout")
public String getDailyWorkout() {
return myCoach.getDailyWorkout();
}
}
Explicação:
@Qualifier("cricketCoach")
: indica que o Spring deve injetar o bean com IDcricketCoach
.- O nome do bean é, por padrão, o nome da classe com a primeira letra em minúsculo:
CricketCoach
→cricketCoach
.
Você também poderia usar outros beans, como:
baseballCoach
trackCoach
tennisCoach
Também Funciona com Injeção via Setter
Se estiver usando injeção por método setter, você também pode aplicar @Qualifier
.
@Component
public class DemoController {
private Coach myCoach;
@Autowired
@Qualifier("cricketCoach")
public void setCoach(Coach myCoach) {
this.myCoach = myCoach;
}
}
@Qualifier
Sobre a Anotação A anotação @Qualifier
é usada para ajudar o Spring a decidir qual bean deve ser injetado, quando há múltiplas opções disponíveis.
Ela pode ser usada em:
- Parâmetros de métodos
- Métodos setters
- Campos (atributos)
45. Qualifiers - Coding - Parte 1
Voltando para injeção via construtor
Vamos ajustar o controlador para usar injeção de dependência via construtor:
@RestController
public class DemoController {
private Coach myCoach;
@Autowired
public DemoController(Coach myCoach) {
this.myCoach = myCoach;
}
@GetMapping("/dailyworkout")
public String getDailyWorkout() {
return myCoach.getDailyWorkout();
}
}
Coach
Criando múltiplas implementações da interface Vamos criar várias classes que implementam a interface Coach
. Cada classe representa um tipo diferente de treinador:
@Component
public class CricketCoach implements Coach {
public String getDailyWorkout() {
return "Treine arremesso rápido por 15 minutos";
}
}
@Component
public class TrackCoach implements Coach {
public String getDailyWorkout() {
return "Corra uma prova intensa de 5km!";
}
}
@Component
public class BaseballCoach implements Coach {
public String getDailyWorkout() {
return "Pratique rebatidas por 30 minutos";
}
}
@Component
public class TennisCoach implements Coach {
public String getDailyWorkout() {
return "Treine seu voleio de backhand";
}
}
46. Qualifiers - Coding - Parte 2
Coach
Problema: múltiplos beans do tipo Quando tentamos executar a aplicação, recebemos o seguinte erro:
Parameter 0 of constructor in com.juhmaran.springcoredemo.rest.DemoController required a single bean, but 4 were found:
- baseballCoach
- cricketCoach
- tennisCoach
- trackCoach
Isso acontece porque temos várias implementações da interface Coach
, e o Spring não sabe qual delas deve injetar no controlador.
@Qualifier
para especificar o bean
Solução: usar Para resolver esse problema, podemos usar a anotação @Qualifier
e indicar qual implementação deve ser usada:
@RestController
public class DemoController {
private Coach myCoach;
@Autowired
public DemoController(@Qualifier("baseballCoach") Coach myCoach) {
this.myCoach = myCoach;
}
@GetMapping("/dailyworkout")
public String getDailyWorkout() {
return myCoach.getDailyWorkout();
}
}
Importante: o valor passado no @Qualifier
deve ser o nome do bean, que por padrão é o nome da classe com a primeira letra minúscula. Exemplo:
- Classe
BaseballCoach
→ Bean ID:baseballCoach
- Classe
TrackCoach
→ Bean ID:trackCoach
Testando diferentes implementações
Se alterarmos o @Qualifier
para outro bean, o comportamento muda. Por exemplo:
// Usando o TrackCoach
@Qualifier("trackCoach")
Resultado no navegador:
"Corra uma prova intensa de 5km!"
// Usando o CricketCoach
@Qualifier("cricketCoach")
Resultado no navegador:
"Treine arremesso rápido por 15 minutos"
Conclusão
Com a anotação @Qualifier
, conseguimos dizer ao Spring exatamente qual implementação usar, resolvendo o problema de ambiguidade quando existem múltiplos beans do mesmo tipo.
Essa abordagem é muito útil quando estamos trabalhando com injeção de dependências e queremos manter o controle sobre qual implementação está sendo usada.