From 3ca77831e199b178f814be86078ab471b52f7f9c Mon Sep 17 00:00:00 2001 From: Peter Rietzler Date: Fri, 10 Feb 2017 09:11:26 +0100 Subject: [PATCH] DATACMNS-989 - Use exclude filters when scanning for custom repository implementations. The detection algorithm for custom repository implementations now considers the exclude filters declared in the overall repository setup (XML and annotations). Original pull request: #195. --- .../data/repository/cdi/CdiRepositoryBean.java | 4 +++- .../AnnotationRepositoryConfigurationSource.java | 3 ++- .../config/CustomRepositoryImplementationDetector.java | 7 ++++++- .../config/RepositoryBeanDefinitionBuilder.java | 3 ++- .../config/RepositoryConfigurationSource.java | 9 +++++++++ .../config/RepositoryConfigurationSourceSupport.java | 3 ++- .../config/XmlRepositoryConfigurationSource.java | 3 ++- .../data/repository/config/MyOtherRepository.java | 2 +- .../repository/config/MyOtherRepositoryExtensions.java | 5 +++++ .../data/repository/config/MyOtherRepositoryImpl.java | 8 ++++++++ ...BeanDefinitionRegistrarSupportIntegrationTests.java | 10 +++++++++- .../config/excluded/MyOtherRepositoryImpl.java | 10 ++++++++++ 12 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 src/test/java/org/springframework/data/repository/config/MyOtherRepositoryExtensions.java create mode 100644 src/test/java/org/springframework/data/repository/config/MyOtherRepositoryImpl.java create mode 100644 src/test/java/org/springframework/data/repository/config/excluded/MyOtherRepositoryImpl.java diff --git a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java index 49590d198..73805c7b1 100644 --- a/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java +++ b/src/main/java/org/springframework/data/repository/cdi/CdiRepositoryBean.java @@ -37,6 +37,7 @@ import javax.enterprise.inject.spi.PassivationCapable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.core.type.filter.TypeFilter; import org.springframework.data.repository.config.CustomRepositoryImplementationDetector; import org.springframework.data.repository.config.DefaultRepositoryConfiguration; import org.springframework.util.Assert; @@ -49,6 +50,7 @@ import org.springframework.util.StringUtils; * @author Dirk Mahler * @author Oliver Gierke * @author Mark Paluch + * @author Peter Rietzler */ public abstract class CdiRepositoryBean implements Bean, PassivationCapable { @@ -244,7 +246,7 @@ public abstract class CdiRepositoryBean implements Bean, PassivationCapabl String className = getCustomImplementationClassName(repositoryType, cdiRepositoryConfiguration); AbstractBeanDefinition beanDefinition = detector.detectCustomImplementation(className, - Collections.singleton(repositoryType.getPackage().getName())); + Collections.singleton(repositoryType.getPackage().getName()), Collections.emptySet()); if (beanDefinition == null) { return null; 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 60a028ddf..37952d642 100644 --- a/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/AnnotationRepositoryConfigurationSource.java @@ -45,6 +45,7 @@ import org.springframework.util.StringUtils; * * @author Oliver Gierke * @author Thomas Darimont + * @author Peter Rietzler */ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigurationSourceSupport { @@ -179,7 +180,7 @@ public class AnnotationRepositoryConfigurationSource extends RepositoryConfigura * @see org.springframework.data.repository.config.RepositoryConfigurationSourceSupport#getExcludeFilters() */ @Override - protected Iterable getExcludeFilters() { + public Iterable getExcludeFilters() { return parseFilters("excludeFilters"); } diff --git a/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java b/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java index e4b5262f3..7e4f702b6 100644 --- a/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java +++ b/src/main/java/org/springframework/data/repository/config/CustomRepositoryImplementationDetector.java @@ -29,6 +29,7 @@ import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.core.type.classreading.MetadataReaderFactory; import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.core.type.filter.TypeFilter; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -37,6 +38,7 @@ import org.springframework.util.StringUtils; * * @author Oliver Gierke * @author Mark Paluch + * @author Peter Rietzler */ public class CustomRepositoryImplementationDetector { @@ -74,7 +76,7 @@ public class CustomRepositoryImplementationDetector { * @param basePackages must not be {@literal null}. * @return the {@code AbstractBeanDefinition} of the custom implementation or {@literal null} if none found */ - public AbstractBeanDefinition detectCustomImplementation(String className, Iterable basePackages) { + public AbstractBeanDefinition detectCustomImplementation(String className, Iterable basePackages, Iterable excludeFilters) { Assert.notNull(className, "ClassName must not be null!"); Assert.notNull(basePackages, "BasePackages must not be null!"); @@ -89,6 +91,9 @@ public class CustomRepositoryImplementationDetector { provider.setResourcePattern(String.format(CUSTOM_IMPLEMENTATION_RESOURCE_PATTERN, className)); provider.setMetadataReaderFactory(metadataReaderFactory); provider.addIncludeFilter(new RegexPatternTypeFilter(pattern)); + for(TypeFilter excludeFilter : excludeFilters) { + provider.addExcludeFilter(excludeFilter); + } Set definitions = new HashSet(); diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java index 68f0d754c..74907c4be 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryBeanDefinitionBuilder.java @@ -33,6 +33,7 @@ import org.springframework.util.StringUtils; * Builder to create {@link BeanDefinitionBuilder} instance to eventually create Spring Data repository instances. * * @author Oliver Gierke + * @author Peter Rietzler */ class RepositoryBeanDefinitionBuilder { @@ -128,7 +129,7 @@ class RepositoryBeanDefinitionBuilder { } AbstractBeanDefinition beanDefinition = implementationDetector - .detectCustomImplementation(configuration.getImplementationClassName(), configuration.getBasePackages()); + .detectCustomImplementation(configuration.getImplementationClassName(), configuration.getBasePackages(), configuration.getConfigurationSource().getExcludeFilters()); if (null == beanDefinition) { return null; diff --git a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java index 556644dde..e475cab08 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSource.java @@ -20,6 +20,7 @@ import java.util.Collection; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.filter.TypeFilter; import org.springframework.data.repository.query.QueryLookupStrategy; /** @@ -27,6 +28,7 @@ import org.springframework.data.repository.query.QueryLookupStrategy; * * @author Oliver Gierke * @author Thomas Darimont + * @author Peter Rietzler */ public interface RepositoryConfigurationSource { @@ -108,4 +110,11 @@ public interface RepositoryConfigurationSource { * @since 1.9 */ boolean usesExplicitFilters(); + + /** + * Return the {@link TypeFilter}s to define which types to exclude when scanning for repositories or repository implementations. + * + * @return must not be {@literal null}. + */ + Iterable getExcludeFilters(); } 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 140ee627d..3072d9c66 100644 --- a/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java +++ b/src/main/java/org/springframework/data/repository/config/RepositoryConfigurationSourceSupport.java @@ -31,6 +31,7 @@ import org.springframework.util.Assert; * * @author Oliver Gierke * @author Thomas Darimont + * @author Peter Rietzler */ public abstract class RepositoryConfigurationSourceSupport implements RepositoryConfigurationSource { @@ -80,7 +81,7 @@ public abstract class RepositoryConfigurationSourceSupport implements Repository * * @return must not be {@literal null}. */ - protected Iterable getExcludeFilters() { + public Iterable getExcludeFilters() { return Collections.emptySet(); } 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 861008bee..a282bdbfc 100644 --- a/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java +++ b/src/main/java/org/springframework/data/repository/config/XmlRepositoryConfigurationSource.java @@ -34,6 +34,7 @@ import org.w3c.dom.Element; * * @author Oliver Gierke * @author Thomas Darimont + * @author Peter Rietzler */ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSourceSupport { @@ -121,7 +122,7 @@ public class XmlRepositoryConfigurationSource extends RepositoryConfigurationSou * @see org.springframework.data.repository.config.RepositoryConfigurationSourceSupport#getExcludeFilters() */ @Override - protected Iterable getExcludeFilters() { + public Iterable getExcludeFilters() { return excludeFilters; } diff --git a/src/test/java/org/springframework/data/repository/config/MyOtherRepository.java b/src/test/java/org/springframework/data/repository/config/MyOtherRepository.java index 5a88c822a..c337e8d48 100644 --- a/src/test/java/org/springframework/data/repository/config/MyOtherRepository.java +++ b/src/test/java/org/springframework/data/repository/config/MyOtherRepository.java @@ -18,6 +18,6 @@ package org.springframework.data.repository.config; import org.springframework.data.repository.Repository; import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSourceUnitTests.Person; -interface MyOtherRepository extends Repository { +interface MyOtherRepository extends Repository, MyOtherRepositoryExtensions { } diff --git a/src/test/java/org/springframework/data/repository/config/MyOtherRepositoryExtensions.java b/src/test/java/org/springframework/data/repository/config/MyOtherRepositoryExtensions.java new file mode 100644 index 000000000..6652184b4 --- /dev/null +++ b/src/test/java/org/springframework/data/repository/config/MyOtherRepositoryExtensions.java @@ -0,0 +1,5 @@ +package org.springframework.data.repository.config; + +public interface MyOtherRepositoryExtensions { + String getImplementationId(); +} diff --git a/src/test/java/org/springframework/data/repository/config/MyOtherRepositoryImpl.java b/src/test/java/org/springframework/data/repository/config/MyOtherRepositoryImpl.java new file mode 100644 index 000000000..305a0a4a9 --- /dev/null +++ b/src/test/java/org/springframework/data/repository/config/MyOtherRepositoryImpl.java @@ -0,0 +1,8 @@ +package org.springframework.data.repository.config; + +public class MyOtherRepositoryImpl implements MyOtherRepositoryExtensions { + @Override + public String getImplementationId() { + return getClass().getName(); + } +} diff --git a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java index 4a901e14a..1a8ba7d81 100644 --- a/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java +++ b/src/test/java/org/springframework/data/repository/config/RepositoryBeanDefinitionRegistrarSupportIntegrationTests.java @@ -23,18 +23,21 @@ import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupportUnitTests.DummyConfigurationExtension; /** * Integration tests for {@link RepositoryBeanDefinitionRegistrarSupport}. * * @author Oliver Gierke + * @author Peter Rietzler */ public class RepositoryBeanDefinitionRegistrarSupportIntegrationTests { @Configuration - @EnableRepositories + @EnableRepositories(excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*\\.excluded\\..*")) static class SampleConfig { } @@ -59,6 +62,11 @@ public class RepositoryBeanDefinitionRegistrarSupportIntegrationTests { } } + @Test // DATACMNS-989 + public void duplicateImplementationsMayBeExcludedViaFilters() { + assertThat(context.getBean(MyOtherRepository.class).getImplementationId(), is(MyOtherRepositoryImpl.class.getName())); + } + @Test // DATACMNS-47 public void testBootstrappingWithInheritedConfigClasses() { diff --git a/src/test/java/org/springframework/data/repository/config/excluded/MyOtherRepositoryImpl.java b/src/test/java/org/springframework/data/repository/config/excluded/MyOtherRepositoryImpl.java new file mode 100644 index 000000000..261110979 --- /dev/null +++ b/src/test/java/org/springframework/data/repository/config/excluded/MyOtherRepositoryImpl.java @@ -0,0 +1,10 @@ +package org.springframework.data.repository.config.excluded; + +import org.springframework.data.repository.config.MyOtherRepositoryExtensions; + +public class MyOtherRepositoryImpl implements MyOtherRepositoryExtensions { + @Override + public String getImplementationId() { + return getClass().getName(); + } +}