19‐Annotation Autowiring and Qualifiers - JulianeMaran32/Java-with-Spring-Boot GitHub Wiki

44. Qualificadores (@Qualifier) – Visão Geral

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

Solução: Use @Qualifier para Especificar

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 ID cricketCoach.
  • O nome do bean é, por padrão, o nome da classe com a primeira letra em minúsculo:
    CricketCoachcricketCoach.

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;
    }
}

Sobre a Anotação @Qualifier

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();
    }

}

Criando múltiplas implementações da interface Coach

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

Problema: múltiplos beans do tipo Coach

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.

Solução: usar @Qualifier para especificar o bean

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.