
# @Qualifier

`@Qualifier('...')` picks one bean among several of the same type, by a label or a bean name.

## Why

When several beans share a type, the container needs to know which one to inject. [@Primary](primary.md) gives a default. `@Qualifier` selects a specific one where the default is not wanted.

It has two sides:

- **on a bean declaration** (a class or a `@Bean` method) it gives the bean a label;
- **on an injection point** (a constructor parameter, a field, a setter, a `@Bean` parameter) it selects the bean with that label, or the bean with that name or alias.

Without any annotation, a parameter named like a bean also selects it: a parameter `frenchGreeter` gets the bean named `frenchGreeter`.

Lookups in code take a qualifier too: `context.getBean<Greeter>(qualifier: 'fr')`.

## Example

```dart
import 'package:spring_core_dart/spring_core_dart.dart';

abstract interface class Greeter {
  String greet(String name);
}

@Component()
@Primary()
class EnglishGreeter implements Greeter {
  @override
  String greet(String name) => 'Hello $name';
}

// Labelled 'fr'.
@Component()
@Qualifier('fr')
class FrenchGreeter implements Greeter {
  @override
  String greet(String name) => 'Bonjour $name';
}

// This page is French, whatever the default greeter is.
@Service()
class Welcome {
  Welcome(@Qualifier('fr') this.greeter);
  final Greeter greeter;
}

// A bean name works as a qualifier too.
@Service()
class Banner {
  @Autowired()
  @Qualifier('englishGreeter')
  late final Greeter greeter;
}
```

## Parameters

| Name | Type | Default | Meaning |
|---|---|---|---|
| `value` (positional) | `String` | required | The label, or a bean name or alias. |

## In Spring (Java)

```java
@Component
@Qualifier("fr")
class FrenchGreeter implements Greeter { ... }

@Service
class Welcome {
  Welcome(@Qualifier("fr") Greeter greeter) { ... }
}
```

Difference that matters: in Spring, a custom qualifier annotation (an annotation meta-annotated with `@Qualifier`) matches by its type and attributes. Here annotations are not read at run time, so qualifiers match by their value only.

## See also

- [@Primary](primary.md), [@Fallback](fallback.md)
- [@Autowired](autowired.md)
- [Jakarta annotations](jakarta.md) (`@Named`, `@Resource`)
- [@Bean](bean.md) (`defaultCandidate`)
