
# @Scope

`@Scope(...)` sets how many instances of a bean exist and how long each one lives.

## Why

Without `@Scope` a bean is a **singleton**: one instance for the whole context, created at startup and shared by everyone who injects it. That is right for most services.

Choose another scope when a bean holds state that must not be shared:

- `ScopeType.prototype`: a new instance for every injection and every lookup. For builders, commands, objects with per-use state. The container does not track prototypes, so their `@PreDestroy` methods never run.
- a custom scope name: one instance per span that you define, such as a screen, a session or a job. Register the scope on the bean factory with `registerScope` before the context starts.

### Shorter scopes inside singletons

A singleton keeps what it was injected with. A screen-scoped bean injected directly into a singleton would stay the first screen's instance forever (the container logs a warning). With `proxyMode: ScopedProxyMode.targetClass` (or `interfaces`) the singleton gets a generated proxy instead. Every call on the proxy asks the scope for the current instance. An [ObjectProvider](object-provider.md) is the other way to reach the current instance.

The proxied type must be implementable from generated code: an interface, or a class without private members, not generic.

## Example

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

// Each user of a cart gets their own instance.
@Component()
@Scope(ScopeType.prototype)
class ShoppingCart {
  final items = <String>[];
}

// One instance per open screen. Services see the current screen's
// state through a generated proxy.
@Component()
@Scope('screen', proxyMode: ScopedProxyMode.targetClass)
class ScreenState {
  String title = '';

  @PreDestroy()
  void clear() => title = '';
}

@Service()
class Analytics {
  Analytics(this.state); // the proxy, not a fixed instance
  final ScreenState state;

  String currentScreen() => state.title;
}
```

Registering the custom scope and ending it:

```dart
// SimpleMapScope keeps instances in a map until destroy() is called.
final screen = SimpleMapScope(conversationId: 'checkout');

final context = AnnotationConfigApplicationContext([appBeans]);
context.beanFactory.registerScope('screen', screen); // before refresh
context.refresh();

context.getBean<ScreenState>().title = 'Checkout';
// ... when the screen closes:
screen.destroy(); // runs @PreDestroy of ScreenState; next lookup is fresh
```

A scope of your own implements `CustomScope` (`get`, `remove`, `registerDestructionCallback`, `conversationId`).

## Parameters

| Name | Type | Default | Meaning |
|---|---|---|---|
| `value` (positional) | `String` | required | The scope name: `ScopeType.singleton`, `ScopeType.prototype` or the name of a registered custom scope. |
| `proxyMode` | `ScopedProxyMode` | `ScopedProxyMode.no` | `no` injects the instance directly. `interfaces` and `targetClass` inject a generated proxy that asks the scope on every call. |

Related types:

| Type | Meaning |
|---|---|
| `ScopeType.singleton` / `ScopeType.prototype` | The names of the two built-in scopes. |
| `ScopedProxyMode` | `no`, `interfaces`, `targetClass`. |
| `CustomScope` | The interface of a custom scope (Spring's `Scope`). |
| `SimpleMapScope` | A ready-made custom scope backed by a map, emptied by `destroy()`. |

## In Spring (Java)

```java
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
class ShoppingCart { ... }

@Component
@Scope(value = "screen", proxyMode = ScopedProxyMode.TARGET_CLASS)
class ScreenState { ... }

beanFactory.registerScope("screen", new MyScreenScope());
```

Differences that matter:

- Spring's scope interface is called `Scope`. Here that name is the annotation, and the interface is `CustomScope`.
- There is no `ScopedProxyMode.DEFAULT` (`default` is a Dart keyword); `no` is the default.
- `interfaces` and `targetClass` both generate a class that implements the bean's type, because every Dart class is also an interface.
- The target is not registered as a separate `scopedTarget.` bean.

## See also

- [@Lazy](lazy.md)
- [ObjectProvider](object-provider.md)
- [@PreDestroy](pre-destroy.md)
- [ConfigurableListableBeanFactory](configurable-listable-bean-factory.md)
- [ApplicationContext](application-context.md)
