@Primary
@Primary() makes a bean the one injected when several beans have the requested type.
Why
When two beans implement the same interface, asking for that interface is ambiguous, and the startup fails with a NoUniqueBeanDefinitionException. Mark the usual implementation @Primary(). Inject the others with @Qualifier where they are wanted.
Typical cases:
- a default implementation and a specialized one;
- a test that registers a replacement bean marked primary;
- a decorator or composite that wraps the other beans of its type. A bean is never injected into itself, so a
@Primarycomposite that asks forList<Greeter>receives the other greeters.
When a single dependency has several candidates, the container picks, in this order:
- the only candidate;
- the single
@Primaryone (a local@Primarybeats a parent context's; two@Primarycandidates are an error); - the only one that is not @Fallback;
- the one named like the parameter, or the one the
@Qualifiernames.
Example
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';
}
@Component()
class FrenchGreeter implements Greeter {
@override
String greet(String name) => 'Bonjour $name';
}
// Gets the EnglishGreeter: it is primary.
@Service()
class Welcome {
Welcome(this.greeter);
final Greeter greeter;
}
context.getBean<Greeter>() also returns the EnglishGreeter. A List<Greeter> still receives both.
A test can override a bean of the application the same way:
final context = AnnotationConfigApplicationContext([appBeans])
..registerBean<Greeter>((_) => FakeGreeter(), name: 'fakeGreeter', primary: true)
..refresh();
Parameters
None.
In Spring (Java)
@Component
@Primary
class EnglishGreeter implements Greeter { ... }
The meaning is the same.
See also
- @Fallback
- @Qualifier
- @Bean (
defaultCandidate) - Jakarta annotations (
@Priority) - ApplicationContext