AutoConfigurationPackages Class — spring-boot Architecture
Architecture documentation for the AutoConfigurationPackages class in AutoConfigurationPackages.java from the spring-boot codebase.
Entity Profile
Relationship Graph
Source Code
core/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationPackages.java lines 53–230
public abstract class AutoConfigurationPackages {
private static final Log logger = LogFactory.getLog(AutoConfigurationPackages.class);
private static final String BEAN = AutoConfigurationPackages.class.getName();
/**
* Determine if the auto-configuration base packages for the given bean factory are
* available.
* @param beanFactory the source bean factory
* @return true if there are auto-config packages available
*/
public static boolean has(BeanFactory beanFactory) {
return beanFactory.containsBean(BEAN) && !get(beanFactory).isEmpty();
}
/**
* Return the auto-configuration base packages for the given bean factory.
* @param beanFactory the source bean factory
* @return a list of auto-configuration packages
* @throws IllegalStateException if auto-configuration is not enabled
*/
public static List<String> get(BeanFactory beanFactory) {
try {
return beanFactory.getBean(BEAN, BasePackages.class).get();
}
catch (NoSuchBeanDefinitionException ex) {
throw new IllegalStateException("Unable to retrieve @EnableAutoConfiguration base packages");
}
}
/**
* Programmatically registers the auto-configuration package names. Subsequent
* invocations will add the given package names to those that have already been
* registered. You can use this method to manually define the base packages that will
* be used for a given {@link BeanDefinitionRegistry}. Generally it's recommended that
* you don't call this method directly, but instead rely on the default convention
* where the package name is set from your {@code @EnableAutoConfiguration}
* configuration class or classes.
* @param registry the bean definition registry
* @param packageNames the package names to set
*/
public static void register(BeanDefinitionRegistry registry, String... packageNames) {
if (registry.containsBeanDefinition(BEAN)) {
addBasePackages(registry.getBeanDefinition(BEAN), packageNames);
}
else {
RootBeanDefinition beanDefinition = new RootBeanDefinition(BasePackages.class);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
addBasePackages(beanDefinition, packageNames);
registry.registerBeanDefinition(BEAN, beanDefinition);
}
}
private static void addBasePackages(BeanDefinition beanDefinition, String[] additionalBasePackages) {
ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
if (constructorArgumentValues.hasIndexedArgumentValue(0)) {
ValueHolder indexedArgumentValue = constructorArgumentValues.getIndexedArgumentValue(0, String[].class);
Assert.state(indexedArgumentValue != null, "'indexedArgumentValue' must not be null");
String[] existingPackages = (String[]) indexedArgumentValue.getValue();
Stream<String> existingPackagesStream = (existingPackages != null) ? Stream.of(existingPackages)
: Stream.empty();
constructorArgumentValues.addIndexedArgumentValue(0,
Stream.concat(existingPackagesStream, Stream.of(additionalBasePackages))
.distinct()
.toArray(String[]::new));
}
else {
constructorArgumentValues.addIndexedArgumentValue(0, additionalBasePackages);
}
}
/**
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*/
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
/**
* Wrapper for a package import.
*/
private static final class PackageImports {
private final List<String> packageNames;
PackageImports(AnnotationMetadata metadata) {
AnnotationAttributes attributes = AnnotationAttributes
.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
Assert.state(attributes != null, "'attributes' must not be null");
List<String> packageNames = new ArrayList<>(Arrays.asList(attributes.getStringArray("basePackages")));
for (Class<?> basePackageClass : attributes.getClassArray("basePackageClasses")) {
packageNames.add(basePackageClass.getPackage().getName());
}
if (packageNames.isEmpty()) {
packageNames.add(ClassUtils.getPackageName(metadata.getClassName()));
}
this.packageNames = Collections.unmodifiableList(packageNames);
}
List<String> getPackageNames() {
return this.packageNames;
}
@Override
public boolean equals(Object obj) {
if (obj == null || getClass() != obj.getClass()) {
return false;
}
return this.packageNames.equals(((PackageImports) obj).packageNames);
}
@Override
public int hashCode() {
return this.packageNames.hashCode();
}
@Override
public String toString() {
return "Package Imports " + this.packageNames;
}
}
/**
* Holder for the base package (name may be null to indicate no scanning).
*/
static final class BasePackages {
private final List<String> packages;
private boolean loggedBasePackageInfo;
BasePackages(String... names) {
List<String> packages = new ArrayList<>();
for (String name : names) {
if (StringUtils.hasText(name)) {
packages.add(name);
}
}
this.packages = packages;
}
List<String> get() {
if (!this.loggedBasePackageInfo) {
if (this.packages.isEmpty()) {
if (logger.isWarnEnabled()) {
logger.warn("@EnableAutoConfiguration was declared on a class "
+ "in the default package. Automatic @Repository and "
+ "@Entity scanning is not enabled.");
}
}
else {
if (logger.isDebugEnabled()) {
String packageNames = StringUtils.collectionToCommaDelimitedString(this.packages);
logger.debug("@EnableAutoConfiguration was declared on a class in the package '" + packageNames
+ "'. Automatic @Repository and @Entity scanning is enabled.");
}
}
this.loggedBasePackageInfo = true;
}
return this.packages;
}
}
}
Domain
Source
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free