
# @Autowired

`@Autowired()` asks the container to inject beans into a field, a setter or a method, or chooses which constructor to call.

## Why

Constructor parameters of a bean are injected without any annotation. That is the usual way and needs no `@Autowired`. Use the annotation in these cases:

- **on a field or setter**: to assign it after construction. Fields must be public and settable (`late final` or non-final). Private fields cannot be injected this way, because the generated code lives in another library; inject them through a constructor parameter (`this._repo`).
- **on a method**: to call it after construction with injected arguments.
- **on a constructor**: to choose it when the class has several. Several constructors may be `@Autowired(required: false)`; the container uses the one with the most parameters whose beans exist.

What an injection point can receive:

- a single bean of its type;
- `List<T>`, `Set<T>` or `Map<String, T>`: every bean of `T`. Only a `List` is sorted (by `Ordered`, `@Order`, `@Priority`);
- `ObjectProvider<T>`: a handle that looks the bean up later;
- the container's own objects: `BeanFactory`, `ApplicationContext`, `ApplicationEventPublisher`, `ResourceLoader`, `Environment`.

A nullable type makes a dependency optional: it receives `null` when there is no bean. `required: false` only matters on constructors; on fields, setters and methods it fails the build.

## Example

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

abstract interface class PaymentGateway {
  void charge(double amount);
}

abstract interface class DiscountRule {
  double apply(double total);
}

abstract interface class Clock {
  DateTime now();
}

class AuditLog {}

@Service()
class Checkout {
  // A field, set after the constructor ran.
  @Autowired()
  late final PaymentGateway gateway;

  // Every DiscountRule bean, sorted by @Order.
  @Autowired()
  late final List<DiscountRule> rules;

  // Optional: null when no AuditLog bean exists.
  @Autowired()
  AuditLog? audit;

  // A method, called once with injected arguments.
  @Autowired()
  void init(Clock clock) => startedAt = clock.now();

  DateTime? startedAt;

  void pay(double total) {
    var amount = total;
    for (final rule in rules) {
      amount = rule.apply(amount);
    }
    gateway.charge(amount);
  }
}

// Two constructors: the container calls the one with the most
// parameters it can satisfy.
@Service()
class Notifier {
  @Autowired(required: false)
  Notifier() : clock = null;

  @Autowired(required: false)
  Notifier.withClock(Clock this.clock);

  final Clock? clock;
}
```

## Parameters

| Name | Type | Default | Meaning |
|---|---|---|---|
| `required` | `bool` | `true` | On a constructor, `false` makes it one of several candidates. Elsewhere, use a nullable type instead. |

## In Spring (Java)

```java
@Service
class Checkout {
  @Autowired PaymentGateway gateway;
  @Autowired List<DiscountRule> rules;

  @Autowired
  void init(Clock clock) { startedAt = clock.now(); }
}
```

Differences that matter:

- Spring injects private fields by reflection. Here only public fields and setters can be injected.
- `required = false` on a field or method is Spring's way to make it optional. Here a nullable type does that.
- `refresh()` checks every injection point before any bean is created. A missing or ambiguous bean fails the startup with an `UnsatisfiedDependencyException` that names the bean and the injection point.

## See also

- [@Qualifier](qualifier.md), [@Primary](primary.md)
- [@Lazy](lazy.md)
- [ObjectProvider](object-provider.md)
- [Jakarta annotations](jakarta.md) (`@Inject`, `@Resource`)
- [@Value](../config/value.md)
- [@Configurable](configurable.md)
