selectAutoConfigurations function
- List<
BeanModule> modules, { - Map<
BeanModule, AutoConfigurationModule> metadata = const {}, - Iterable<
Type> excludeTypes = const [], - Iterable<
String> excludeNames = const [],
Takes the auto-configuration modules of the libraries an application uses, drops the excluded ones and returns the rest in the order they must be registered.
SpringApplication calls it on every start with the modules the
generator found, the application's exclude / excludeName and the
spring.autoconfigure.exclude property. Applications never call it;
a test tool that builds a context from auto-configuration, such as
ApplicationContextRunner, does.
Order matters because a library's @ConditionalOnMissingBean only sees
the beans registered before it. The modules are sorted by
AutoConfigurationModule.order (from metadata; 0 when absent),
then by name, then by their position in modules. Then the before and
after lists move modules around; a cycle among them throws a
StateError (AutoConfigure cycle detected between ...).
excludeTypes and excludeNames name what to leave out. A name
matches a module by its BeanModule.name, or an @AutoConfiguration
class by its name (CacheAutoConfiguration) or full name
(package:x/src/y.dart#CacheAutoConfiguration), found through the
source of the bean definitions the class produced. Excluding a class
removes its bean definitions, its @Imports (registrars and
selectors) and its conditional @PropertySources; excluding a module
removes all of it. A Type in excludeTypes that matches nothing
throws a StateError (... could not be excluded because they are not auto-configuration classes); an unknown name is ignored, as Spring
Boot ignores a class that is not on the classpath.
In before and after, a class is matched by its short name only.
Spring (Java): the exclusion of @SpringBootApplication(exclude = ...)
and the order of AutoConfigurationSorter (by name, then
@AutoConfigureOrder, then @AutoConfigureBefore / After).
Implementation
List<BeanModule> selectAutoConfigurations(
List<BeanModule> modules, {
Map<BeanModule, AutoConfigurationModule> metadata = const {},
Iterable<Type> excludeTypes = const [],
Iterable<String> excludeNames = const [],
}) {
final typeNames = {for (final type in excludeTypes) '$type'};
final names = {
...typeNames,
for (final name in excludeNames)
if (name.trim().isNotEmpty) name.trim(),
};
final matched = <String>{};
final entries = <_Entry>[];
for (final module in modules) {
if (names.contains(module.name)) {
matched.add(module.name);
continue;
}
// Whether [source] belongs to an excluded class (recorded as matched).
bool excluded(String? source) {
final owner = _owner(source);
final hit = owner == null
? const <String>{}
: {owner.$1, owner.$2}.intersection(names);
matched.addAll(hit);
return hit.isNotEmpty;
}
final kept = [
for (final definition in module.definitions)
if (!excluded(definition.source)) definition,
];
// The imports of the classes left (an import belongs to its importer,
// else to the class of its condition group).
final keptImports = [
for (final declaration in module.registrars)
if (!excluded(
declaration.importer ??
declaration.conditions
.whereType<ConditionGroup>()
.firstOrNull
?.key,
))
declaration,
];
final keptSources = [
for (final declaration in module.propertySources)
if (!excluded(
declaration.conditions.whereType<ConditionGroup>().firstOrNull?.key,
))
declaration,
];
final info = metadata[module];
entries.add(
_Entry(
kept.length == module.definitions.length &&
keptImports.length == module.registrars.length &&
keptSources.length == module.propertySources.length
? module
: _withDefinitions(module, kept, keptImports, keptSources),
info?.order ?? 0,
info?.before ?? const [],
info?.after ?? const [],
{
for (final definition in module.definitions)
?_owner(definition.source)?.$1,
},
),
);
}
final missing = typeNames.difference(matched);
if (missing.isNotEmpty) {
throw StateError(
'The following classes could not be excluded because they are not '
'auto-configuration classes:\n'
'${[for (final name in missing) '\t- $name'].join('\n')}',
);
}
return _sort(entries);
}