From fce40e981c542eba4d2c45c0a2b1ff6da31c6335 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Mon, 26 Jun 2017 16:01:55 +0200 Subject: [PATCH] DATACMNS-1098 - RepositoryComponentScanner now exposes BeanDefinitionRegistry. We now override ClassPathScanningCandidateComponentProvider's getRegistry() to make sure custom conditions on repository candidates can use the currently available BeanDefinitionRegistry in their implementations. To achieve that we forward the BeanDefinitionRegistry at hand through the configuration infrastructure (both XML and annotation side of things). --- ...notationRepositoryConfigurationSource.java | 5 ++-- ...ositoryBeanDefinitionRegistrarSupport.java | 8 +++---- .../config/RepositoryComponentProvider.java | 18 ++++++++++++-- .../RepositoryConfigurationSourceSupport.java | 11 ++++++--- .../XmlRepositoryConfigurationSource.java | 2 +- ...epositoryConfigurationSourceUnitTests.java | 14 +++++++---- .../RepositoryComponentProviderUnitTests.java | 24 +++++++++++++++---- ...ositoryConfigurationDelegateUnitTests.java | 4 +++- 8 files changed, 65 insertions(+), 21 deletions(-) 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 967f98a88..675824750 100644 --- a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java @@ -25,6 +25,7 @@ import java.util.Set; import java.util.regex.Pattern; import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.FilterType; import org.springframework.core.annotation.AnnotationAttributes; import org.springframework.core.env.Environment; @@ -76,9 +77,9 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura * @param environment */ public AnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class annotation, - ResourceLoader resourceLoader, Environment environment) { + ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry) { - super(environment, resourceLoader.getClassLoader()); + super(environment, resourceLoader.getClassLoader(), registry); Assert.notNull(metadata, "Metadata must not be null!"); Assert.notNull(annotation, "Annotation must not be null!"); 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 183d75d6b..c4f336298 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupport.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2017 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. @@ -32,8 +32,8 @@ import org.springframework.util.Assert; * * @author Oliver Gierke */ -public abstract class RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar, - ResourceLoaderAware, EnvironmentAware { +public abstract class RepositoryBeanDefinitionRegistrarSupport + implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware { private ResourceLoader resourceLoader; private Environment environment; @@ -72,7 +72,7 @@ public abstract class RepositoryBeanDefinitionRegistrarSupport implements Import } AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource( - annotationMetadata, getAnnotation(), resourceLoader, environment); + annotationMetadata, getAnnotation(), resourceLoader, environment, registry); RepositoryConfigurationExtension extension = getExtension(); RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java b/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java index fedda5f32..4523f6c43 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2017 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. @@ -22,6 +22,7 @@ import java.util.Set; import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.AnnotationConfigUtils; import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.core.type.classreading.MetadataReader; @@ -47,6 +48,7 @@ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentPro private static final String METHOD_NOT_PUBLIC = "AnnotationConfigUtils.processCommonDefinitionAnnotations(…) is not public! Make sure you're using Spring 3.2.5 or better. The class was loaded from %s."; private boolean considerNestedRepositoryInterfaces; + private BeanDefinitionRegistry registry; /** * Creates a new {@link RepositoryComponentProvider} using the given {@link TypeFilter} to include components to be @@ -55,13 +57,16 @@ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentPro * @param includeFilters the {@link TypeFilter}s to select repository interfaces to consider, must not be * {@literal null}. */ - public RepositoryComponentProvider(Iterable includeFilters) { + public RepositoryComponentProvider(Iterable includeFilters, BeanDefinitionRegistry registry) { super(false); assertRequiredSpringVersionPresent(); Assert.notNull(includeFilters, "Include filters must not be null!"); + Assert.notNull(registry, "BeanDefinitionRegistry must not be null!"); + + this.registry = registry; if (includeFilters.iterator().hasNext()) { for (TypeFilter filter : includeFilters) { @@ -129,6 +134,15 @@ class RepositoryComponentProvider extends ClassPathScanningCandidateComponentPro return candidates; } + /* + * (non-Javadoc) + * @see org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#getRegistry() + */ + @Override + protected BeanDefinitionRegistry getRegistry() { + return registry; + } + /** * @return the considerNestedRepositoryInterfaces */ 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 2ea1798b1..eebfdb2a7 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -18,6 +18,7 @@ package org.springframework.data.repository.config; import java.util.Collections; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.filter.TypeFilter; @@ -38,6 +39,7 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository private final Environment environment; private final RepositoryBeanNameGenerator beanNameGenerator; + private final BeanDefinitionRegistry registry; /** * Creates a new {@link RepositoryConfigurationSourceSupport} with the given environment. @@ -45,13 +47,16 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository * @param environment must not be {@literal null}. * @param classLoader must not be {@literal null}. */ - public RepositoryConfigurationSourceSupport(Environment environment, ClassLoader classLoader) { + public RepositoryConfigurationSourceSupport(Environment environment, ClassLoader classLoader, + BeanDefinitionRegistry registry) { 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.registry = registry; } /* @@ -61,10 +66,10 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository @Override public Streamable getCandidates(ResourceLoader loader) { - RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters()); + RepositoryComponentProvider scanner = new RepositoryComponentProvider(getIncludeFilters(), registry); scanner.setConsiderNestedRepositoryInterfaces(shouldConsiderNestedRepositories()); - scanner.setResourceLoader(loader); scanner.setEnvironment(environment); + scanner.setResourceLoader(loader); getExcludeFilters().forEach(it -> scanner.addExcludeFilter(it)); 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 6fceacd61..0713d1ee8 100644 --- a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java @@ -64,7 +64,7 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou */ public XmlRepositoryConfigurationSource(Element element, ParserContext context, Environment environment) { - super(environment, context.getReaderContext().getResourceLoader().getClassLoader()); + super(environment, context.getReaderContext().getResourceLoader().getClassLoader(), context.getRegistry()); Assert.notNull(element, "Element must not be null!"); Assert.notNull(context, "Context must not be null!"); diff --git a/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java b/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java index 3f04ee9ee..a15e184ed 100755 --- a/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSourceUnitTests.java @@ -16,6 +16,7 @@ package org.springframework.data.repository.config; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -23,6 +24,7 @@ import java.lang.annotation.RetentionPolicy; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; @@ -45,6 +47,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { RepositoryConfigurationSource source; Environment environment; ResourceLoader resourceLoader; + BeanDefinitionRegistry registry; @Before public void setUp() { @@ -52,8 +55,10 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { AnnotationMetadata annotationMetadata = new StandardAnnotationMetadata(SampleConfiguration.class, true); environment = new StandardEnvironment(); resourceLoader = new DefaultResourceLoader(); + registry = mock(BeanDefinitionRegistry.class); + source = new AnnotationRepositoryConfigurationSource(annotationMetadata, EnableRepositories.class, resourceLoader, - environment); + environment, registry); } @Test // DATACMNS-47 @@ -110,7 +115,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { StandardAnnotationMetadata metadata = new StandardAnnotationMetadata( getClass().getClassLoader().loadClass("TypeInDefaultPackage"), true); RepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata, - EnableRepositories.class, resourceLoader, environment); + EnableRepositories.class, resourceLoader, environment, registry); assertThat(configurationSource.getBasePackages()).contains(""); } @@ -127,7 +132,7 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { AnnotationMetadata metadata = new StandardAnnotationMetadata(ConfigWithSampleAnnotation.class, true); RepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(metadata, - SampleAnnotation.class, resourceLoader, environment); + SampleAnnotation.class, resourceLoader, environment, registry); assertThat(configurationSource.getRepositoryBaseClassName()).isNotPresent(); } @@ -135,7 +140,8 @@ public class AnnotationRepositoryConfigurationSourceUnitTests { private AnnotationRepositoryConfigurationSource getConfigSource(Class type) { AnnotationMetadata metadata = new StandardAnnotationMetadata(type, true); - return new AnnotationRepositoryConfigurationSource(metadata, EnableRepositories.class, resourceLoader, environment); + return new AnnotationRepositoryConfigurationSource(metadata, EnableRepositories.class, resourceLoader, environment, + registry); } public static class Person {} diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java index dface79fc..088fb2668 100755 --- a/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryComponentProviderUnitTests.java @@ -16,8 +16,8 @@ package org.springframework.data.repository.config; import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Set; @@ -26,6 +26,7 @@ import org.hamcrest.BaseMatcher; import org.hamcrest.Description; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.core.type.filter.AssignableTypeFilter; import org.springframework.core.type.filter.TypeFilter; import org.springframework.data.repository.Repository; @@ -40,10 +41,12 @@ import org.springframework.data.repository.sample.SampleAnnotatedRepository; */ public class RepositoryComponentProviderUnitTests { + BeanDefinitionRegistry registry = mock(BeanDefinitionRegistry.class); + @Test public void findsAnnotatedRepositoryInterface() { - RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.emptyList()); + RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.emptyList(), registry); Set components = provider.findCandidateComponents("org.springframework.data.repository.sample"); assertThat(components).hasSize(3); @@ -56,7 +59,7 @@ public class RepositoryComponentProviderUnitTests { List filters = Collections.singletonList(new AssignableTypeFilter(MyOtherRepository.class)); - RepositoryComponentProvider provider = new RepositoryComponentProvider(filters); + RepositoryComponentProvider provider = new RepositoryComponentProvider(filters, registry); Set components = provider.findCandidateComponents("org.springframework.data.repository"); assertThat(components).hasSize(1); @@ -66,7 +69,7 @@ public class RepositoryComponentProviderUnitTests { @Test // DATACMNS-90 public void shouldConsiderNestedRepositoryInterfacesIfEnabled() { - RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.emptyList()); + RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.emptyList(), registry); provider.setConsiderNestedRepositoryInterfaces(true); Set components = provider.findCandidateComponents("org.springframework.data.repository.config"); @@ -76,6 +79,19 @@ public class RepositoryComponentProviderUnitTests { assertThat(components).extracting(BeanDefinition::getBeanClassName).contains(nestedRepositoryClassName); } + @Test(expected = IllegalArgumentException.class) // DATACMNS-1098 + public void rejectsNullBeanDefinitionRegistry() { + new RepositoryComponentProvider(Collections.emptyList(), null); + } + + @Test // DATACMNS-1098 + public void exposesBeanDefinitionRegistry() { + + RepositoryComponentProvider provider = new RepositoryComponentProvider(Collections.emptyList(), registry); + + assertThat(provider.getRegistry()).isEqualTo(registry); + } + static class BeanDefinitionOfTypeMatcher extends BaseMatcher { private final Class expectedType; diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java index 10d011926..e1f02a2af 100644 --- a/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryConfigurationDelegateUnitTests.java @@ -45,8 +45,10 @@ public class RepositoryConfigurationDelegateUnitTests { StandardEnvironment environment = new StandardEnvironment(); GenericApplicationContext context = new GenericApplicationContext(); + RepositoryConfigurationSource configSource = new AnnotationRepositoryConfigurationSource( - new StandardAnnotationMetadata(TestConfig.class, true), EnableRepositories.class, context, environment); + new StandardAnnotationMetadata(TestConfig.class, true), EnableRepositories.class, context, environment, + context.getDefaultListableBeanFactory()); RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configSource, context, environment);