
# BeanPostProcessor

A `BeanPostProcessor` sees every bean as it is created, and may change or replace it before the container hands it out.

## Why

Cross-cutting features are built this way: wrapping beans in proxies (AOP, caching, transactions), checking or logging every bean, injecting something special. Applications rarely write one; the starters and annotations bring the ones they need.

A processor has two methods. Both receive the bean and its name and return the object to go on with. The defaults return the bean unchanged.

- `postProcessBeforeInitialization` runs after injection and the [aware callbacks](aware.md), before the init callbacks.
- `postProcessAfterInitialization` runs after the init callbacks. What it returns, for example a proxy, is what the container exposes and injects. It also runs on [FactoryBean](factory-bean.md) products.

Init callbacks always run on the raw instance, even when `postProcessBeforeInitialization` returned a wrapper.

### Registration and order

An application context finds the post-processor beans by itself and creates them before the other beans. They are ordered in three groups: `PriorityOrdered`, then `Ordered` or `@Order`, then the rest; within a group by order value. The beans of a group are created only after the previous group is registered, so a `PriorityOrdered` processor already applies to the creation of the `Ordered` ones.

`@PostConstruct` methods run at a fixed place in that chain, as in Spring: after the `postProcessBeforeInitialization` of the `PriorityOrdered` processors with a lower order, before the `Ordered` and plain ones. `afterPropertiesSet` and the init method run after all of them.

On a bare factory, register processors with `beanFactory.addBeanPostProcessor(...)`. They run in the order added.

A processor only sees beans created after it is registered. Keep its own dependencies few: a bean it depends on is created before all processors exist, and misses some of them.

### Specialized processors

| Class | Adds |
|---|---|
| `DestructionAwareBeanPostProcessor` | `postProcessBeforeDestruction(bean, beanName)`, called before the bean's `@PreDestroy` and destroy callbacks, and `requiresDestruction(bean)`. |
| `InstantiationAwareBeanPostProcessor` | `postProcessBeforeInstantiation(beanType, beanName)`, which may return the bean itself and skip its creation; `postProcessAfterInstantiation(bean, beanName)`, which may skip field and setter injection; `postProcessProperties(bean, beanName)`, after that injection. |
| `SmartInstantiationAwareBeanPostProcessor` | `predictBeanType(beanType, beanName)`, the type of a bean the processor replaces. |
| `MergedBeanDefinitionPostProcessor` | `postProcessMergedBeanDefinition(definition, beanType, beanName)`, once per definition, and `resetBeanDefinition(beanName)`. |

These are for framework code. Applications almost never need them.

## Example

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

const log = SpringLog('my_app.startup');

// Logs how long the init callbacks of each bean took
// (afterPropertiesSet and the init method).
@Component()
class TimingPostProcessor extends BeanPostProcessor implements Ordered {
  final _started = <String, Stopwatch>{};

  @override
  int get order => 100;

  @override
  Object postProcessBeforeInitialization(Object bean, String beanName) {
    _started[beanName] = Stopwatch()..start();
    return bean;
  }

  @override
  Object postProcessAfterInitialization(Object bean, String beanName) {
    final watch = _started.remove(beanName);
    if (watch != null) {
      log.info('$beanName ready in ${watch.elapsedMicroseconds} us');
    }
    return bean;
  }
}

// Closes every bean that is a Sink, when the context closes.
@Component()
class ClosingPostProcessor extends DestructionAwareBeanPostProcessor {
  @override
  bool requiresDestruction(Object bean) => bean is Sink<Object?>;

  @override
  void postProcessBeforeDestruction(Object bean, String beanName) =>
      (bean as Sink<Object?>).close();
}
```

## Members

| Method | Default | Meaning |
|---|---|---|
| `Object postProcessBeforeInitialization(Object bean, String beanName)` | returns `bean` | Called after injection and the aware callbacks, before the init callbacks. |
| `Object postProcessAfterInitialization(Object bean, String beanName)` | returns `bean` | Called after the init callbacks. The result is what the container exposes. |

The order of creation for one bean:

1. constructor;
2. injected fields, setters and `@Autowired` methods;
3. aware callbacks;
4. `postProcessBeforeInitialization`, with `@PostConstruct` at its place in the chain;
5. `InitializingBean.afterPropertiesSet`;
6. the `initMethod` of `@Bean`;
7. `postProcessAfterInitialization`.

## In Spring (Java)

```java
@Component
class TimingPostProcessor implements BeanPostProcessor, Ordered {
  @Override
  public Object postProcessAfterInitialization(Object bean, String name) {
    log.info("ready: " + name);
    return bean;
  }

  @Override
  public int getOrder() { return 100; }
}
```

Differences that matter:

- `BeanPostProcessor` is an abstract class with default methods. Extend it.
- `SmartInstantiationAwareBeanPostProcessor` has no `getEarlyBeanReference` or `determineCandidateConstructors`: circular references are always an error, and the generator picks the constructor.
- Proxies are generated classes, not run-time subclasses.

## See also

- [BeanFactoryPostProcessor](bean-factory-post-processor.md)
- [@PostConstruct](post-construct.md)
- [@PreDestroy](pre-destroy.md)
- [Aware interfaces](aware.md)
- [ConfigurableListableBeanFactory](configurable-listable-bean-factory.md) (`addBeanPostProcessor`)
- [AOP](../aop/index.md)
