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.
This commit is contained in:
Peter Rietzler
2017-02-10 09:11:26 +01:00
committed by Oliver Gierke
parent 9dbe75aa4e
commit 04aa75c5e3
12 changed files with 59 additions and 8 deletions

View File

@@ -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<T> implements Bean<T>, PassivationCapable {
@@ -244,7 +246,7 @@ public abstract class CdiRepositoryBean<T> implements Bean<T>, PassivationCapabl
String className = getCustomImplementationClassName(repositoryType, cdiRepositoryConfiguration);
AbstractBeanDefinition beanDefinition = detector.detectCustomImplementation(className,
Collections.singleton(repositoryType.getPackage().getName()));
Collections.singleton(repositoryType.getPackage().getName()), Collections.<TypeFilter>emptySet());
if (beanDefinition == null) {
return null;

View File

@@ -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<TypeFilter> getExcludeFilters() {
public Iterable<TypeFilter> getExcludeFilters() {
return parseFilters("excludeFilters");
}

View File

@@ -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<String> basePackages) {
public AbstractBeanDefinition detectCustomImplementation(String className, Iterable<String> basePackages, Iterable<TypeFilter> 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<BeanDefinition> definitions = new HashSet<BeanDefinition>();

View File

@@ -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;

View File

@@ -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<TypeFilter> getExcludeFilters();
}

View File

@@ -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<TypeFilter> getExcludeFilters() {
public Iterable<TypeFilter> getExcludeFilters() {
return Collections.emptySet();
}

View File

@@ -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<TypeFilter> getExcludeFilters() {
public Iterable<TypeFilter> getExcludeFilters() {
return excludeFilters;
}

View File

@@ -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<Person, Long> {
interface MyOtherRepository extends Repository<Person, Long>, MyOtherRepositoryExtensions {
}

View File

@@ -0,0 +1,5 @@
package org.springframework.data.repository.config;
public interface MyOtherRepositoryExtensions {
String getImplementationId();
}

View File

@@ -0,0 +1,8 @@
package org.springframework.data.repository.config;
public class MyOtherRepositoryImpl implements MyOtherRepositoryExtensions {
@Override
public String getImplementationId() {
return getClass().getName();
}
}

View File

@@ -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() {

View File

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