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(); + } +}