DATACMNS-102 - Polishing.

Changed RepositoryConfiguration to return Streamable over Iterable. A couple of code reorganizations, suppression of raw type. Turned abstract helper classes into interfaces where possible. A couple of typos in JavaDoc.

Original pull request: #222.
This commit is contained in:
Oliver Gierke
2017-06-13 17:08:52 +02:00
parent 92e8907030
commit 663ae9b4bf
9 changed files with 121 additions and 104 deletions

View File

@@ -23,6 +23,7 @@ import java.util.Optional;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.data.util.Streamable;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -64,7 +65,7 @@ public class DefaultRepositoryConfiguration<T extends RepositoryConfigurationSou
* (non-Javadoc)
* @see org.springframework.data.repository.config.RepositoryConfiguration#getBasePackages()
*/
public Iterable<String> getBasePackages() {
public Streamable<String> getBasePackages() {
return configurationSource.getBasePackages();
}
@@ -161,7 +162,7 @@ public class DefaultRepositoryConfiguration<T extends RepositoryConfigurationSou
* @see org.springframework.data.repository.config.RepositoryConfiguration#getExcludeFilters()
*/
@Override
public Iterable<TypeFilter> getExcludeFilters() {
public Streamable<TypeFilter> getExcludeFilters() {
return configurationSource.getExcludeFilters();
}
}

View File

@@ -16,11 +16,11 @@
package org.springframework.data.repository.config;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -41,6 +41,7 @@ import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.core.support.RepositoryFragment;
import org.springframework.data.repository.core.support.RepositoryFragmentsFactoryBean;
import org.springframework.data.repository.query.ExtensionAwareEvaluationContextProvider;
import org.springframework.data.util.StreamUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -143,6 +144,7 @@ class RepositoryBeanDefinitionBuilder {
return builder;
}
@SuppressWarnings("deprecation")
private Optional<String> registerCustomImplementation(RepositoryConfiguration<?> configuration) {
String beanName = configuration.getImplementationBeanName();
@@ -162,7 +164,6 @@ class RepositoryBeanDefinitionBuilder {
}
it.setSource(configuration.getSource());
registry.registerBeanDefinition(beanName, it);
return beanName;
@@ -215,7 +216,6 @@ class RepositoryBeanDefinitionBuilder {
fragmentConfiguration.getBeanDefinition().ifPresent(bd -> {
bd.setSource(repositoryConfiguration.getSource());
registry.registerBeanDefinition(beanName, bd);
});
}
@@ -245,6 +245,7 @@ class RepositoryBeanDefinitionBuilder {
}
private ClassMetadata getClassMetadata(String className) {
try {
return metadataReaderFactory.getMetadataReader(className).getClassMetadata();
} catch (IOException e) {
@@ -254,13 +255,8 @@ class RepositoryBeanDefinitionBuilder {
private static List<TypeFilter> getExclusions(RepositoryConfiguration<?> configuration) {
List<TypeFilter> exclusions = new ArrayList<>();
for (TypeFilter typeFilter : configuration.getExcludeFilters()) {
exclusions.add(typeFilter);
}
exclusions.add(new AnnotationTypeFilter(NoRepositoryBean.class));
return exclusions;
return Stream
.concat(configuration.getExcludeFilters().stream(), Stream.of(new AnnotationTypeFilter(NoRepositoryBean.class)))//
.collect(StreamUtils.toUnmodifiableList());
}
}

View File

@@ -19,6 +19,7 @@ import java.util.Optional;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.util.Streamable;
/**
* Configuration information for a single repository instance.
@@ -33,7 +34,7 @@ public interface RepositoryConfiguration<T extends RepositoryConfigurationSource
*
* @return
*/
Iterable<String> getBasePackages();
Streamable<String> getBasePackages();
/**
* Returns the interface name of the repository.
@@ -117,5 +118,5 @@ public interface RepositoryConfiguration<T extends RepositoryConfigurationSource
*
* @return
*/
Iterable<TypeFilter> getExcludeFilters();
Streamable<TypeFilter> getExcludeFilters();
}

View File

@@ -28,13 +28,13 @@ import org.springframework.util.StringUtils;
* Fragment configuration consisting of an interface name and the implementation class name.
*
* @author Mark Paluch
* @author Oliver Gierke
* @since 2.0
*/
@Value
public class RepositoryFragmentConfiguration {
String interfaceName;
String className;
String interfaceName, className;
Optional<AbstractBeanDefinition> beanDefinition;
/**
@@ -67,8 +67,8 @@ public class RepositoryFragmentConfiguration {
Assert.notNull(beanDefinition, "Bean definition must not be null!");
this.interfaceName = interfaceName;
this.beanDefinition = Optional.of(beanDefinition);
this.className = beanDefinition.getBeanClassName();
this.beanDefinition = Optional.of(beanDefinition);
}
/**

View File

@@ -46,10 +46,10 @@ import org.springframework.util.Assert;
* Implementations of method lookup functions.
*
* @author Mark Paluch
* @author Oliver Gierke
* @since 2.0
*/
public abstract class MethodLookups {
private MethodLookups() {}
interface MethodLookups {
/**
* Direct method lookup filtering on exact method name, parameter count and parameter types.
@@ -102,23 +102,34 @@ public abstract class MethodLookups {
*
* @author Mark Paluch
*/
private static class RepositoryAwareMethodLookup implements MethodLookup {
static class RepositoryAwareMethodLookup implements MethodLookup {
private static final TypeVariable<Class<Repository>>[] PARAMETERS = Repository.class.getTypeParameters();
@SuppressWarnings("rawtypes") private static final TypeVariable<Class<Repository>>[] PARAMETERS = Repository.class
.getTypeParameters();
private static final String DOMAIN_TYPE_NAME = PARAMETERS[0].getName();
private static final String ID_TYPE_NAME = PARAMETERS[1].getName();
private final ResolvableType entityType;
private final ResolvableType idType;
private final ResolvableType entityType, idType;
private final Class<?> repositoryInterface;
/**
* Creates a new {@link RepositoryAwareMethodLookup} for the given {@link RepositoryMetadata}.
*
* @param repositoryMetadata must not be {@literal null}.
*/
public RepositoryAwareMethodLookup(RepositoryMetadata repositoryMetadata) {
Assert.notNull(repositoryMetadata, "Repository metadata must not be null!");
this.entityType = ResolvableType.forClass(repositoryMetadata.getDomainType());
this.idType = ResolvableType.forClass(repositoryMetadata.getIdType());
this.repositoryInterface = repositoryMetadata.getRepositoryInterface();
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.MethodLookup#getLookups()
*/
@Override
public List<MethodPredicate> getLookups() {
@@ -214,15 +225,20 @@ public abstract class MethodLookups {
*
* @author Mark Paluch
*/
private static class ReactiveTypeInteropMethodLookup extends RepositoryAwareMethodLookup {
static class ReactiveTypeInteropMethodLookup extends RepositoryAwareMethodLookup {
private final RepositoryMetadata repositoryMetadata;
public ReactiveTypeInteropMethodLookup(RepositoryMetadata repositoryMetadata) {
super(repositoryMetadata);
this.repositoryMetadata = repositoryMetadata;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.MethodLookups.RepositoryAwareMethodLookup#getLookups()
*/
@Override
public List<MethodPredicate> getLookups() {
@@ -408,5 +424,4 @@ public abstract class MethodLookups {
}
}
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.repository.core.support;
import lombok.AccessLevel;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import java.lang.reflect.Method;
@@ -66,14 +67,13 @@ import org.springframework.util.ReflectionUtils;
public class RepositoryComposition {
private static final BiFunction<Method, Object[], Object[]> PASSTHRU_ARG_CONVERTER = (methodParameter, o) -> o;
private static final RepositoryComposition EMPTY = new RepositoryComposition(RepositoryFragments.empty(),
MethodLookups.direct(), PASSTHRU_ARG_CONVERTER);
private final Map<Method, Optional<Method>> methodCache = new ConcurrentReferenceHashMap<>();
private final RepositoryFragments fragments;
private final MethodLookup methodLookup;
private final BiFunction<Method, Object[], Object[]> argumentConverter;
private final @Getter RepositoryFragments fragments;
private final @Getter MethodLookup methodLookup;
private final @Getter BiFunction<Method, Object[], Object[]> argumentConverter;
/**
* Create an empty {@link RepositoryComposition}.
@@ -86,7 +86,7 @@ public class RepositoryComposition {
/**
* Create a {@link RepositoryComposition} for just a single {@code implementation} with {@link MethodLookups#direct())
* method lokup.
* method lookup.
*
* @param implementation must not be {@literal null}.
* @return the {@link RepositoryComposition} for a single {@code implementation}.
@@ -98,7 +98,7 @@ public class RepositoryComposition {
/**
* Create a {@link RepositoryComposition} from {@link RepositoryFragment fragments} with
* {@link MethodLookups#direct()) method lokup.
* {@link MethodLookups#direct()) method lookup.
*
* @param fragments must not be {@literal null}.
* @return the {@link RepositoryComposition} from {@link RepositoryFragment fragments}.
@@ -109,7 +109,7 @@ public class RepositoryComposition {
/**
* Create a {@link RepositoryComposition} from {@link RepositoryFragment fragments} with
* {@link MethodLookups#direct()) method lokup.
* {@link MethodLookups#direct()) method lookup.
*
* @param fragments must not be {@literal null}.
* @return the {@link RepositoryComposition} from {@link RepositoryFragment fragments}.
@@ -121,7 +121,7 @@ public class RepositoryComposition {
/**
* Create a {@link RepositoryComposition} from {@link RepositoryFragments} and {@link RepositoryMetadata} with
* {@link MethodLookups#direct()) method lokup.
* {@link MethodLookups#direct()) method lookup.
*
* @param fragments must not be {@literal null}.
* @return the {@link RepositoryComposition} from {@link RepositoryFragments fragments}.
@@ -173,18 +173,6 @@ public class RepositoryComposition {
return new RepositoryComposition(fragments, methodLookup, argumentConverter);
}
public MethodLookup getMethodLookup() {
return methodLookup;
}
public RepositoryFragments getFragments() {
return fragments;
}
public BiFunction<Method, Object[], Object[]> getArgumentConverter() {
return argumentConverter;
}
/**
* Return {@literal true} if this {@link RepositoryComposition} contains no {@link RepositoryFragment fragments}.
*
@@ -341,6 +329,10 @@ public class RepositoryComposition {
return fragments.isEmpty();
}
/*
* (non-Javadoc)
* @see java.lang.Iterable#iterator()
*/
@Override
public Iterator<RepositoryFragment<?>> iterator() {
return fragments.iterator();
@@ -349,6 +341,7 @@ public class RepositoryComposition {
/**
* @return {@link Stream} of {@link RepositoryFragment fragments}.
*/
@Override
public Stream<RepositoryFragment<?>> stream() {
return fragments.stream();
}
@@ -360,23 +353,6 @@ public class RepositoryComposition {
return stream().flatMap(RepositoryFragment::methods);
}
static Optional<Method> findMethod(InvokedMethod invokedMethod, MethodLookup lookup,
Supplier<Stream<Method>> methodStreamSupplier) {
for (MethodPredicate methodPredicate : lookup.getLookups()) {
Optional<Method> resolvedMethod = methodStreamSupplier.get()
.filter(it -> methodPredicate.test(invokedMethod, it)) //
.findFirst();
if (resolvedMethod.isPresent()) {
return resolvedMethod;
}
}
return Optional.empty();
}
/**
* Invoke {@link Method} by resolving the
*
@@ -401,7 +377,25 @@ public class RepositoryComposition {
return method.invoke(target, args);
}
/* (non-Javadoc)
private static Optional<Method> findMethod(InvokedMethod invokedMethod, MethodLookup lookup,
Supplier<Stream<Method>> methodStreamSupplier) {
for (MethodPredicate methodPredicate : lookup.getLookups()) {
Optional<Method> resolvedMethod = methodStreamSupplier.get()
.filter(it -> methodPredicate.test(invokedMethod, it)) //
.findFirst();
if (resolvedMethod.isPresent()) {
return resolvedMethod;
}
}
return Optional.empty();
}
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override

View File

@@ -47,7 +47,7 @@ import org.springframework.util.ReflectionUtils;
* @since 2.0
* @see RepositoryComposition
*/
public abstract class RepositoryFragment<T> {
public interface RepositoryFragment<T> {
/**
* Create an implemented {@link RepositoryFragment} backed by the {@code implementation} object.
@@ -56,7 +56,7 @@ public abstract class RepositoryFragment<T> {
* @return
*/
public static <T> RepositoryFragment<T> implemented(T implementation) {
return new ImplementedRepositoryFragment<>(Optional.empty(), implementation);
return new ImplementedRepositoryFragment<T>(Optional.empty(), implementation);
}
/**
@@ -87,25 +87,32 @@ public abstract class RepositoryFragment<T> {
* @param method must not be {@literal null}.
* @return {@literal true} if the method was found or {@literal false} otherwise
*/
public boolean hasMethod(Method method) {
default boolean hasMethod(Method method) {
Assert.notNull(method, "Method must not be null!");
return ReflectionUtils.findMethod(getSignatureContributor(), method.getName(), method.getParameterTypes()) != null;
}
/**
* @return the class/interface providing signatures for this {@link RepositoryFragment}.
*/
protected abstract Class<?> getSignatureContributor();
/**
* @return the optional implementation. Only available for implemented fragments. Structural fragments return always
* {@link Optional#empty()}.
*/
public Optional<T> getImplementation() {
default Optional<T> getImplementation() {
return Optional.empty();
}
/**
* @return a {@link Stream} of methods exposed by this {@link RepositoryFragment}.
*/
default Stream<Method> methods() {
return Arrays.stream(getSignatureContributor().getMethods());
}
/**
* @return the class/interface providing signatures for this {@link RepositoryFragment}.
*/
Class<?> getSignatureContributor();
/**
* Implement a structural {@link RepositoryFragment} given its {@code implementation} object. Returns an implemented
* {@link RepositoryFragment}.
@@ -113,22 +120,16 @@ public abstract class RepositoryFragment<T> {
* @param implementation must not be {@literal null}.
* @return a new implemented {@link RepositoryFragment} for {@code implementation}.
*/
public abstract RepositoryFragment<T> withImplementation(T implementation);
/**
* @return a {@link Stream} of methods exposed by this {@link RepositoryFragment}.
*/
public Stream<Method> methods() {
return Arrays.stream(getSignatureContributor().getMethods());
}
RepositoryFragment<T> withImplementation(T implementation);
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = false)
static class StructuralRepositoryFragment<T> extends RepositoryFragment<T> {
static class StructuralRepositoryFragment<T> implements RepositoryFragment<T> {
private final @NonNull Class<T> interfaceOrImplementation;
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFragment#getSignatureContributor()
*/
@Override
@@ -136,7 +137,8 @@ public abstract class RepositoryFragment<T> {
return interfaceOrImplementation;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFragment#withImplementation(java.lang.Object)
*/
@Override
@@ -149,19 +151,19 @@ public abstract class RepositoryFragment<T> {
*/
@Override
public String toString() {
return String.format("StructuralRepositoryFragment %s", ClassUtils.getShortName(interfaceOrImplementation));
}
}
@RequiredArgsConstructor
@EqualsAndHashCode(callSuper = false)
static class ImplementedRepositoryFragment<T> extends RepositoryFragment<T> {
static class ImplementedRepositoryFragment<T> implements RepositoryFragment<T> {
private final @NonNull Optional<Class<T>> interfaceClass;
private final @NonNull T implementation;
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFragment#getSignatureContributor()
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -169,7 +171,8 @@ public abstract class RepositoryFragment<T> {
return interfaceClass.orElse((Class) implementation.getClass());
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFragment#getImplementation()
*/
@Override
@@ -177,7 +180,8 @@ public abstract class RepositoryFragment<T> {
return Optional.of(implementation);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.RepositoryFragment#withImplementation(java.lang.Object)
*/
@Override
@@ -185,7 +189,8 @@ public abstract class RepositoryFragment<T> {
return new ImplementedRepositoryFragment<>(interfaceClass, implementation);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override

View File

@@ -53,20 +53,32 @@ public class RepositoryFragmentsFactoryBean<T>
this.fragmentBeanNames = fragmentBeanNames;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void afterPropertiesSet() {
List<RepositoryFragment<?>> fragments = (List) fragmentBeanNames.stream()
.map(it -> beanFactory.getBean(it, RepositoryFragment.class)).collect(Collectors.toList());
List<RepositoryFragment<?>> fragments = (List) fragmentBeanNames.stream() //
.map(it -> beanFactory.getBean(it, RepositoryFragment.class)) //
.collect(Collectors.toList());
this.repositoryFragments = RepositoryFragments.from(fragments);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
@Override
@@ -81,12 +93,4 @@ public class RepositoryFragmentsFactoryBean<T>
public Class<?> getObjectType() {
return RepositoryComposition.class;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}