
# @Configuration

`@Configuration()` marks a class whose [@Bean](bean.md) methods create beans.

## Why

Some objects cannot carry `@Component()`:

- the class comes from another package (an HTTP client, a database driver);
- the constructor needs values that are not beans (a URL from the settings);
- creating the object takes a few lines of setup code.

A configuration class groups the methods that create such objects. Each `@Bean` method returns one bean, and its parameters are injected like constructor parameters. The configuration class is a bean too.

If every object of yours can carry `@Component()`, you do not need a configuration class.

### Calls between `@Bean` methods

By default (`proxyBeanMethods: true`) the container creates a generated subclass of your configuration class. Its `@Bean` methods return the container's bean. So when one `@Bean` method calls another, it gets the existing singleton, not a second object. A prototype-scoped `@Bean` still gives a new instance per call. Static `@Bean` methods are not intercepted.

Because of the subclass, a class with instance `@Bean` methods must be extendable from another library: not `final`, `sealed` or `interface`, with a public generative constructor. Otherwise the build fails.

With `proxyBeanMethods: false` ("lite" mode) the methods run as written and there is no subclass. Then take other beans as method parameters instead of calling the other methods.

`@Lazy`, `@Profile` and conditions on the class apply to all its `@Bean` methods, unless a method says otherwise (`@Lazy(false)`).

## Example

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

// Classes from "another package": they cannot be annotated.
class Connection {
  Connection(this.url);
  final String url;
  void connect() {}
  void close() {}
}

class UserStore {
  UserStore(this.connection);
  final Connection connection;
}

abstract interface class Clock {
  DateTime now();
}

class SystemClock implements Clock {
  @override
  DateTime now() => DateTime.now();
}

class Scheduler {
  Scheduler(this.clock);
  final Clock clock;
}

@Configuration()
class DataConfig {
  // The URL comes from the configuration. connect() runs once the
  // bean is created; close() is called at shutdown (inferred).
  @Bean(initMethod: 'connect')
  Connection connection(@Value(r'${db.url}') String url) => Connection(url);

  // The Connection bean is injected as a parameter.
  @Bean()
  UserStore userStore(Connection connection) => UserStore(connection);

  @Bean()
  Clock clock() => SystemClock();

  // Calling clock() returns the container's singleton, not a new clock.
  @Bean()
  Scheduler scheduler() => Scheduler(clock());
}

// Lite mode: no generated subclass. Dependencies come in as parameters.
@Configuration(proxyBeanMethods: false)
class LiteConfig {
  @Bean()
  Scheduler backupScheduler(Clock clock) => Scheduler(clock);
}
```

## Parameters

| Name | Type | Default | Meaning |
|---|---|---|---|
| `name` | `String?` | `null` | The bean name of the configuration class. `null` gives the class name in lowerCamelCase. Named, unlike `@Component`'s positional name. |
| `proxyBeanMethods` | `bool` | `true` | Whether a generated subclass makes `@Bean` methods return the container's beans. With `false` the methods are called as written. |

## In Spring (Java)

```java
@Configuration
class DataConfig {
  @Bean(initMethod = "connect")
  Connection connection(@Value("${db.url}") String url) {
    return new Connection(url);
  }

  @Bean
  UserStore userStore(Connection connection) {
    return new UserStore(connection);
  }

  @Bean Clock clock() { return new SystemClock(); }

  @Bean Scheduler scheduler() { return new Scheduler(clock()); }
}

@Configuration(proxyBeanMethods = false)
class LiteConfig { ... }
```

Differences that matter:

- Spring creates the subclass at run time with CGLIB. Here the generator writes it into the `.spring.dart` file, which is why the class must be extendable from another library.
- Spring writes `@Configuration("name")`. Here the name is the named argument `name:`.

## See also

- [@Bean](bean.md)
- [@Import](import.md)
- [@Lazy](lazy.md), [@Profile](profile.md), [@Conditional](conditional.md)
- [@Value](../config/value.md)
- [@PropertySource](../config/property-source.md)
