Aware interfaces
A bean that implements an *Aware interface receives its own name, the bean factory, the context or another container object through a method call.
Why
Constructor injection is usually simpler: a bean can inject BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher or MessageSource directly. The aware interfaces are for the remaining cases:
- a bean that needs its own bean name, for example several beans of one class that each read their own settings;
- a base class shared by many beans, whose constructors you do not want to change;
- objects the container creates but does not inject: an
ImportSelectoror anImportBeanDefinitionRegistrarcan implementEnvironmentAware,BeanFactoryAwareandResourceLoaderAware, which are called before it runs; - framework classes.
Each setter is called once, after injection and before the init callbacks (@PostConstruct, afterPropertiesSet, the init method). The order is:
BeanNameAware.setBeanName;BeanFactoryAware.setBeanFactory;EnvironmentAware.setEnvironment;EmbeddedValueResolverAware.setEmbeddedValueResolver;ResourceLoaderAware.setResourceLoader;ApplicationEventPublisherAware.setApplicationEventPublisher;MessageSourceAware.setMessageSource;ApplicationContextAware.setApplicationContext.
The first two are called by the bean factory. The others are called by ApplicationContextAwareProcessor, a BeanPostProcessor that every context registers. A bare DefaultListableBeanFactory without a context calls only the first two.
Example
import 'package:spring_core_dart/spring_core_dart.dart';
abstract interface class Plugin {
void run();
}
// Two workers of one class, registered as 'importer' and 'exporter'.
// Each reads its own settings, keyed by its bean name.
class Worker implements BeanNameAware, EnvironmentAware {
late final String id;
late final Environment _environment;
@override
void setBeanName(String name) => id = name;
@override
void setEnvironment(Environment environment) => _environment = environment;
int get batchSize =>
int.parse(_environment.getProperty('workers.$id.batch-size') ?? '100');
}
@Configuration()
class WorkerConfig {
@Bean()
Worker importer() => Worker();
@Bean()
Worker exporter() => Worker();
}
// Which plugin runs is decided by name at run time.
@Component()
class PluginLoader implements BeanFactoryAware {
late BeanFactory _factory;
@override
void setBeanFactory(BeanFactory beanFactory) => _factory = beanFactory;
void run(String name) => (_factory.getBeanByName(name) as Plugin).run();
}
// Paths built from properties, resolved at run time.
@Component()
class Paths implements EmbeddedValueResolverAware {
late String cache;
@override
void setEmbeddedValueResolver(StringValueResolver resolver) {
cache = resolver(r"#{'${app.home:/tmp}' + '/cache'}");
}
}
Members
| Interface | Method | Receives |
|---|---|---|
BeanNameAware |
setBeanName(String name) |
The bean's name, never an alias. |
BeanFactoryAware |
setBeanFactory(BeanFactory beanFactory) |
The factory that holds the bean. |
EnvironmentAware |
setEnvironment(Environment environment) |
The context's environment. |
EmbeddedValueResolverAware |
setEmbeddedValueResolver(StringValueResolver resolver) |
A function that resolves ${...} placeholders, then #{...} expressions, like @Value. |
ResourceLoaderAware |
setResourceLoader(ResourceLoader resourceLoader) |
The context, as resource loader. Custom protocols added to it work. |
ApplicationEventPublisherAware |
setApplicationEventPublisher(ApplicationEventPublisher publisher) |
The context, as event publisher. |
MessageSourceAware |
setMessageSource(MessageSource messageSource) |
The context, which looks messages up in the messageSource bean. |
ApplicationContextAware |
setApplicationContext(ApplicationContext applicationContext) |
The context that created the bean. |
Aware is the common supertype. It has no methods.
In Spring (Java)
class Worker implements BeanNameAware, EnvironmentAware {
String id;
Environment environment;
@Override public void setBeanName(String name) { id = name; }
@Override public void setEnvironment(Environment env) { environment = env; }
}
Differences that matter:
StringValueResolveris a function type: callresolver(text)instead ofresolver.resolveStringValue(text).#{null}gives an empty string.BeanClassLoaderAware,ApplicationStartupAwareandServletContextAwaredo not exist.
See also
- ApplicationContext
- Lifecycle and SmartLifecycle
- @PostConstruct
- BeanPostProcessor
- @Import (selectors and registrars)
- Environment
- Placeholders