20‐Primary - JulianeMaran32/Java-with-Spring-Boot GitHub Wiki

47. Primary - Visão Geral

Anotação @Primary

Quando temos várias implementações de uma interface

  • Suponha que tenhamos várias classes que implementam a interface Coach.
  • Anteriormente, resolvemos isso usando a anotação @Qualifier para indicar exatamente qual classe usar.
  • Mas existe uma alternativa...

Solução Alternativa

  • Em vez de dizer explicitamente qual classe usar com @Qualifier, podemos apenas dizer:
    • "Preciso de um Coach, qualquer um serve."
  • A ideia é: se houver várias opções, deixamos o Spring escolher uma como a principal (ou “primária”).
  • Isso é feito usando a anotação @Primary.

Exemplo com Várias Implementações de Coach

@Component
@Primary // Esta é a implementação padrão de Coach
public class TrackCoach implements Coach {
    public String getDailyWorkout() {
        return "Corra uma prova intensa de 5km!";
    }
}

@Component
public class CricketCoach implements Coach {}

@Component
public class BaseballCoach implements Coach {}

@Component
public class TennisCoach implements Coach {}
@RestController
public class DemoController {

    private Coach myCoach;

    // Não precisamos usar @Qualifier
    // O Spring vai usar o Coach marcado com @Primary
    @Autowired
    public DemoController(Coach myCoach) {
        this.myCoach = myCoach;
    }

    @GetMapping("/dailyworkout")
    public String getDailyWorkout() {
        return myCoach.getDailyWorkout();
    }

}

Regras do @Primary

  • Você só pode marcar uma única classe como @Primary.
  • Se marcar mais de uma, o Spring não saberá qual usar e gerará um erro:
Unsatisfied dependency expressed through constructor parameter 0:
No qualifying bean of type 'Coach' available:
more than one 'primary' bean found among candidates: [baseballCoach, cricketCoach, tennisCoach, trackCoach]

Misturando @Primary com @Qualifier

  • É possível usar os dois juntos.
  • Porém, o @Qualifier tem prioridade maior que o @Primary.
@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();
    }

}
@Primary
@Component
public class TrackCoach implements Coach {
    public String getDailyWorkout() {
        return "Corra uma prova intensa de 5km!";
    }
}

Qual usar: @Primary ou @Qualifier?

  • @Primary: Deixa o Spring escolher a implementação padrão.
    • Pode causar erro se mais de uma classe estiver marcada como @Primary.
  • @Qualifier: Você escolhe exatamente qual classe usar.
    • Mais seguro e específico.
    • Tem prioridade maior do que @Primary.
  • Recomendação: Prefira usar @Qualifier sempre que quiser mais controle e clareza.

48. Primary - Codificando

@RestController
public class DemoController {

    private Coach myCoach;

    @Autowired
    public DemoController(Coach myCoach) {
        this.myCoach = myCoach;
    }

    @GetMapping("/dailyworkout")
    public String getDailyWorkout() {
        return myCoach.getDailyWorkout();
    }

}
@Primary
@Component
public class TrackCoach implements Coach {

    @Override
    public String getDailyWorkout() {
        return "Corra uma prova intensa de 5km!";
    }

}

Resultado: Sucesso!

  • A aplicação inicia normalmente.
  • Mesmo com várias implementações da interface Coach, o Spring escolhe a classe TrackCoach, pois está anotada com @Primary.
  • Quando acessamos a URL http://localhost:8080/dailyworkout, recebemos a resposta da TrackCoach.