Allow base packages to be specified on @AutoConfigurationPackage
Closes gh-19023
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -26,8 +26,9 @@ import java.lang.annotation.Target;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Indicates that the package containing the annotated class should be registered with
|
||||
* {@link AutoConfigurationPackages}.
|
||||
* Registers packages with {@link AutoConfigurationPackages}. When no {@link #basePackages
|
||||
* base packages} or {@link #basePackageClasses base package classes} are specified, the
|
||||
* package of the annotated class is registered.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @since 1.3.0
|
||||
@@ -40,4 +41,25 @@ import org.springframework.context.annotation.Import;
|
||||
@Import(AutoConfigurationPackages.Registrar.class)
|
||||
public @interface AutoConfigurationPackage {
|
||||
|
||||
/**
|
||||
* Base packages that should be registered with {@link AutoConfigurationPackages}.
|
||||
* <p>
|
||||
* Use {@link #basePackageClasses} for a type-safe alternative to String-based package
|
||||
* names.
|
||||
* @return the back package names
|
||||
* @since 2.3.0
|
||||
*/
|
||||
String[] basePackages() default {};
|
||||
|
||||
/**
|
||||
* Type-safe alternative to {@link #basePackages} for specifying the packages to be
|
||||
* registered with {@link AutoConfigurationPackages}.
|
||||
* <p>
|
||||
* Consider creating a special no-op marker class or interface in each package that
|
||||
* serves no purpose other than being referenced by this attribute.
|
||||
* @return the base package classes
|
||||
* @since 2.3.0
|
||||
*/
|
||||
Class<?>[] basePackageClasses() default {};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -34,6 +34,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.GenericBeanDefinition;
|
||||
import org.springframework.boot.context.annotation.DeterminableImports;
|
||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -120,12 +121,12 @@ public abstract class AutoConfigurationPackages {
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
|
||||
register(registry, new PackageImport(metadata).getPackageName());
|
||||
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Object> determineImports(AnnotationMetadata metadata) {
|
||||
return Collections.singleton(new PackageImport(metadata));
|
||||
return Collections.singleton(new PackageImports(metadata));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -133,16 +134,28 @@ public abstract class AutoConfigurationPackages {
|
||||
/**
|
||||
* Wrapper for a package import.
|
||||
*/
|
||||
private static final class PackageImport {
|
||||
private static final class PackageImports {
|
||||
|
||||
private final String packageName;
|
||||
private final List<String> packageNames;
|
||||
|
||||
PackageImport(AnnotationMetadata metadata) {
|
||||
this.packageName = ClassUtils.getPackageName(metadata.getClassName());
|
||||
PackageImports(AnnotationMetadata metadata) {
|
||||
AnnotationAttributes attributes = AnnotationAttributes
|
||||
.fromMap(metadata.getAnnotationAttributes(AutoConfigurationPackage.class.getName(), false));
|
||||
List<String> packageNames = new ArrayList<>();
|
||||
for (String basePackage : attributes.getStringArray("basePackages")) {
|
||||
packageNames.add(basePackage);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
String getPackageName() {
|
||||
return this.packageName;
|
||||
List<String> getPackageNames() {
|
||||
return this.packageNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,17 +163,17 @@ public abstract class AutoConfigurationPackages {
|
||||
if (obj == null || getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
return this.packageName.equals(((PackageImport) obj).packageName);
|
||||
return this.packageNames.equals(((PackageImports) obj).packageNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.packageName.hashCode();
|
||||
return this.packageNames.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Package Import " + this.packageName;
|
||||
return "Package Imports " + this.packageNames;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,12 +20,10 @@ import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages.Registrar;
|
||||
import org.springframework.boot.autoconfigure.packagestest.one.FirstConfiguration;
|
||||
import org.springframework.boot.autoconfigure.packagestest.two.SecondConfiguration;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
@@ -41,7 +39,8 @@ public class AutoConfigurationPackagesTests {
|
||||
|
||||
@Test
|
||||
void setAndGet() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigWithRegistrar.class);
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
ConfigWithAutoConfigurationPackage.class);
|
||||
assertThat(AutoConfigurationPackages.get(context.getBeanFactory()))
|
||||
.containsExactly(getClass().getPackage().getName());
|
||||
}
|
||||
@@ -63,9 +62,38 @@ public class AutoConfigurationPackagesTests {
|
||||
assertThat(packages).containsOnly(package1.getName(), package2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenBasePackagesAreSpecifiedThenTheyAreRegistered() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
ConfigWithAutoConfigurationBasePackages.class);
|
||||
List<String> packages = AutoConfigurationPackages.get(context.getBeanFactory());
|
||||
assertThat(packages).containsExactly("com.example.alpha", "com.example.bravo");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenBasePackageClassesAreSpecifiedThenTheirPackagesAreRegistered() {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
|
||||
ConfigWithAutoConfigurationBasePackageClasses.class);
|
||||
List<String> packages = AutoConfigurationPackages.get(context.getBeanFactory());
|
||||
assertThat(packages).containsOnly(FirstConfiguration.class.getPackage().getName(),
|
||||
SecondConfiguration.class.getPackage().getName());
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(AutoConfigurationPackages.Registrar.class)
|
||||
static class ConfigWithRegistrar {
|
||||
@AutoConfigurationPackage
|
||||
static class ConfigWithAutoConfigurationPackage {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigurationPackage(basePackages = { "com.example.alpha", "com.example.bravo" })
|
||||
static class ConfigWithAutoConfigurationBasePackages {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@AutoConfigurationPackage(basePackageClasses = { FirstConfiguration.class, SecondConfiguration.class })
|
||||
static class ConfigWithAutoConfigurationBasePackageClasses {
|
||||
|
||||
}
|
||||
|
||||
@@ -74,11 +102,4 @@ public class AutoConfigurationPackagesTests {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test helper to allow {@link Registrar} to be referenced from other packages.
|
||||
*/
|
||||
public static class TestRegistrar extends Registrar {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -171,12 +171,12 @@ class ImportAutoConfigurationImportSelectorTests {
|
||||
|
||||
@Test
|
||||
void determineImportsShouldNotSetPackageImport() throws Exception {
|
||||
Class<?> packageImportClass = ClassUtils.resolveClassName(
|
||||
"org.springframework.boot.autoconfigure.AutoConfigurationPackages.PackageImport", null);
|
||||
Class<?> packageImportsClass = ClassUtils.resolveClassName(
|
||||
"org.springframework.boot.autoconfigure.AutoConfigurationPackages.PackageImports", null);
|
||||
Set<Object> selectedImports = this.importSelector
|
||||
.determineImports(getAnnotationMetadata(ImportMetaAutoConfigurationExcludeWithUnrelatedOne.class));
|
||||
for (Object selectedImport : selectedImports) {
|
||||
assertThat(selectedImport).isNotInstanceOf(packageImportClass);
|
||||
assertThat(selectedImport).isNotInstanceOf(packageImportsClass);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.packagestest.one;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests.TestRegistrar;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Sample configuration used in {@code AutoConfigurationPackagesTests}.
|
||||
@@ -26,7 +25,7 @@ import org.springframework.context.annotation.Import;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(TestRegistrar.class)
|
||||
@AutoConfigurationPackage
|
||||
public class FirstConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.packagestest.two;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackagesTests.TestRegistrar;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Sample configuration used in {@link AutoConfigurationPackagesTests}.
|
||||
@@ -27,7 +26,7 @@ import org.springframework.context.annotation.Import;
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@Import(TestRegistrar.class)
|
||||
@AutoConfigurationPackage
|
||||
public class SecondConfiguration {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user