@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:

When a single dependency has several candidates, the container picks, in this order:

  1. the only candidate;
  2. the single @Primary one (a local @Primary beats a parent context's; two @Primary candidates are an error);
  3. the only one that is not @Fallback;
  4. the one named like the parameter, or the one the @Qualifier names.

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