diff --git a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java index 7cb93f28e..d274e8ab6 100644 --- a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java @@ -29,6 +29,9 @@ import javax.annotation.Nonnull; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.annotation.AnnotationBeanNameGenerator; +import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.annotation.FilterType; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; @@ -42,6 +45,7 @@ import org.springframework.core.type.filter.RegexPatternTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.data.config.ConfigurationUtils; import org.springframework.data.util.Streamable; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -82,11 +86,31 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura * @param resourceLoader must not be {@literal null}. * @param environment must not be {@literal null}. * @param registry must not be {@literal null}. + * @deprecated since 2.2. Prefer to use overload taking a {@link BeanNameGenerator} additionally. */ + @Deprecated public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class annotation, ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry) { + this(metadata, annotation, resourceLoader, environment, registry, null); + } - super(environment, ConfigurationUtils.getRequiredClassLoader(resourceLoader), registry); + /** + * Creates a new {@link AnnotationRepositoryConfigurationSource} from the given {@link AnnotationMetadata} and + * annotation. + * + * @param metadata must not be {@literal null}. + * @param annotation must not be {@literal null}. + * @param resourceLoader must not be {@literal null}. + * @param environment must not be {@literal null}. + * @param registry must not be {@literal null}. + * @param generator can be {@literal null}. + */ + public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class annotation, + ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry, + @Nullable BeanNameGenerator generator) { + + super(environment, ConfigurationUtils.getRequiredClassLoader(resourceLoader), registry, + defaultBeanNameGenerator(generator)); Assert.notNull(metadata, "Metadata must not be null!"); Assert.notNull(annotation, "Annotation must not be null!"); @@ -397,4 +421,20 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura return new String[0]; } } + + /** + * Returns the {@link BeanNameGenerator} to use falling back to an {@link AnnotationBeanNameGenerator} if either the + * given generator is {@literal null} or it's the one locally declared in {@link ConfigurationClassPostProcessor}'s + * {@code importBeanNameGenerator}. This is to make sure we only use the given {@link BeanNameGenerator} if it was + * customized. + * + * @param generator can be {@literal null}. + * @return + */ + private static BeanNameGenerator defaultBeanNameGenerator(@Nullable BeanNameGenerator generator) { + + return generator == null || ConfigurationClassPostProcessor.IMPORT_BEAN_NAME_GENERATOR.equals(generator) // + ? new AnnotationBeanNameGenerator() // + : generator; + } } diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java index 390c37510..d4efc50a3 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java @@ -21,6 +21,7 @@ import javax.annotation.Nonnull; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; @@ -60,9 +61,11 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport /* * (non-Javadoc) - * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry) + * @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.beans.factory.support.BeanNameGenerator) */ - public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) { + @Override + public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry, + BeanNameGenerator generator) { Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!"); Assert.notNull(registry, "BeanDefinitionRegistry must not be null!"); @@ -74,7 +77,7 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport } AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource( - annotationMetadata, getAnnotation(), resourceLoader, environment, registry); + annotationMetadata, getAnnotation(), resourceLoader, environment, registry, generator); RepositoryConfigurationExtension extension = getExtension(); RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java index a652d9a7a..f32bcd245 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanNameGenerator.java @@ -15,14 +15,13 @@ */ package org.springframework.data.repository.config; -import lombok.RequiredArgsConstructor; - import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.AnnotationBeanNameGenerator; +import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** @@ -33,12 +32,25 @@ import org.springframework.util.ClassUtils; * @author Oliver Gierke * @author Jens Schauder */ -@RequiredArgsConstructor -public class RepositoryBeanNameGenerator { - - private static final SpringDataAnnotationBeanNameGenerator DELEGATE = new SpringDataAnnotationBeanNameGenerator(); +class RepositoryBeanNameGenerator { private final ClassLoader beanClassLoader; + private final SpringDataAnnotationBeanNameGenerator delegate; + + /** + * Creates a new {@link RepositoryBeanNameGenerator} for the given {@link ClassLoader} and {@link BeanNameGenerator}. + * + * @param beanClassLoader must not be {@literal null}. + * @param generator must not be {@literal null}. + */ + public RepositoryBeanNameGenerator(ClassLoader beanClassLoader, BeanNameGenerator generator) { + + Assert.notNull(beanClassLoader, "Bean ClassLoader must not be null!"); + Assert.notNull(generator, "BeanNameGenerator must not be null!"); + + this.beanClassLoader = beanClassLoader; + this.delegate = new SpringDataAnnotationBeanNameGenerator(generator); + } /** * Generate a bean name for the given bean definition. @@ -53,7 +65,7 @@ public class RepositoryBeanNameGenerator { ? (AnnotatedBeanDefinition) definition // : new AnnotatedGenericBeanDefinition(getRepositoryInterfaceFrom(definition)); - return DELEGATE.generateBeanName(beanDefinition); + return delegate.generateBeanName(beanDefinition); } /** diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java index a87fcf005..52a1fdfde 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -22,6 +22,7 @@ import java.util.Collections; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.classreading.MetadataReaderFactory; @@ -53,14 +54,14 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository * @param registry must not be {@literal null}. */ public RepositoryConfigurationSourceSupport(Environment environment, ClassLoader classLoader, - BeanDefinitionRegistry registry) { + BeanDefinitionRegistry registry, BeanNameGenerator generator) { Assert.notNull(environment, "Environment must not be null!"); Assert.notNull(classLoader, "ClassLoader must not be null!"); Assert.notNull(registry, "BeanDefinitionRegistry must not be null!"); this.environment = environment; - this.beanNameGenerator = new RepositoryBeanNameGenerator(classLoader); + this.beanNameGenerator = new RepositoryBeanNameGenerator(classLoader, generator); this.registry = registry; } diff --git a/src/main/java/org/springframework/data/repository/config/SpringDataAnnotationBeanNameGenerator.java b/src/main/java/org/springframework/data/repository/config/SpringDataAnnotationBeanNameGenerator.java index 3690a58b0..80c370904 100644 --- a/src/main/java/org/springframework/data/repository/config/SpringDataAnnotationBeanNameGenerator.java +++ b/src/main/java/org/springframework/data/repository/config/SpringDataAnnotationBeanNameGenerator.java @@ -15,8 +15,12 @@ */ package org.springframework.data.repository.config; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.context.annotation.AnnotationBeanNameGenerator; /** @@ -29,9 +33,10 @@ import org.springframework.context.annotation.AnnotationBeanNameGenerator; * @since 2.0 * @soundtrack Nils Wülker - Never Left At All (feat. Rob Summerfield) */ -public class SpringDataAnnotationBeanNameGenerator { +@RequiredArgsConstructor +class SpringDataAnnotationBeanNameGenerator { - private final AnnotationBeanNameGenerator delegate = new AnnotationBeanNameGenerator(); + private final @NonNull BeanNameGenerator delegate; /** * Generates a bean name for the given {@link BeanDefinition}. diff --git a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java index 7771c3a12..bb9562422 100644 --- a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java @@ -68,7 +68,8 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou */ public XmlRepositoryConfigurationSource(Element element, ParserContext context, Environment environment) { - super(environment, ConfigurationUtils.getRequiredClassLoader(context.getReaderContext()), context.getRegistry()); + super(environment, ConfigurationUtils.getRequiredClassLoader(context.getReaderContext()), context.getRegistry(), + context.getReaderContext().getReader().getBeanNameGenerator()); Assert.notNull(element, "Element must not be null!"); diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java index 03a46e6b2..d6d98a8f8 100755 --- a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportUnitTests.java @@ -27,6 +27,8 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.BeanNameGenerator; +import org.springframework.context.annotation.AnnotationBeanNameGenerator; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.FilterType; import org.springframework.core.env.StandardEnvironment; @@ -64,7 +66,7 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests { AnnotationMetadata metadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); - registrar.registerBeanDefinitions(metadata, registry); + registrar.registerBeanDefinitions(metadata, registry, null); assertBeanDefinitionRegisteredFor("myRepository"); assertBeanDefinitionRegisteredFor("composedRepository"); @@ -78,7 +80,7 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests { AnnotationMetadata metadata = new StandardAnnotationMetadata(FragmentExclusionConfiguration.class, true); - registrar.registerBeanDefinitions(metadata, registry); + registrar.registerBeanDefinitions(metadata, registry, null); assertBeanDefinitionRegisteredFor("repositoryWithFragmentExclusion"); assertNoBeanDefinitionRegisteredFor("excludedRepositoryImpl"); @@ -89,7 +91,7 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests { AnnotationMetadata metadata = new StandardAnnotationMetadata(LimitsImplementationBasePackages.class, true); - registrar.registerBeanDefinitions(metadata, registry); + registrar.registerBeanDefinitions(metadata, registry, null); assertBeanDefinitionRegisteredFor("personRepository"); assertNoBeanDefinitionRegisteredFor("fragmentImpl"); @@ -98,17 +100,30 @@ public class RepositoryBeanDefinitionRegistrarSupportUnitTests { @Test // DATACMNS-360 public void registeredProfileRepositoriesIfProfileActivated() { - StandardAnnotationMetadata metadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); + AnnotationMetadata metadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); environment.setActiveProfiles("profile"); DummyRegistrar registrar = new DummyRegistrar(); registrar.setEnvironment(environment); - - registrar.registerBeanDefinitions(metadata, registry); + registrar.registerBeanDefinitions(metadata, registry, null); assertBeanDefinitionRegisteredFor("myRepository", "profileRepository"); } + @Test // DATACMNS-1497 + public void usesBeanNameGeneratorProvided() { + + AnnotationMetadata metadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); + BeanNameGenerator delegate = new AnnotationBeanNameGenerator(); + + DummyRegistrar registrar = new DummyRegistrar(); + registrar.setEnvironment(environment); + registrar.registerBeanDefinitions(metadata, registry, + (definition, registry) -> delegate.generateBeanName(definition, registry).concat("Hello")); + + assertBeanDefinitionRegisteredFor("myRepositoryHello"); + } + private void assertBeanDefinitionRegisteredFor(String... names) { for (String name : names) { diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java index fcc16c309..6f787c40c 100755 --- a/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryBeanNameGeneratorUnitTests.java @@ -27,6 +27,7 @@ import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefiniti import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.annotation.AnnotationBeanNameGenerator; import org.springframework.context.annotation.ScannedGenericBeanDefinition; import org.springframework.core.type.classreading.MetadataReader; import org.springframework.core.type.classreading.MetadataReaderFactory; @@ -48,7 +49,8 @@ public class RepositoryBeanNameGeneratorUnitTests { @Before public void setUp() { - this.generator = new RepositoryBeanNameGenerator(Thread.currentThread().getContextClassLoader()); + this.generator = new RepositoryBeanNameGenerator(Thread.currentThread().getContextClassLoader(), + new AnnotationBeanNameGenerator()); } @Test