Skip to content

Commit 771347b

Browse files
committed
Revise ClassUtils and ReflectionUtils.
We deprecated `ClassUtils` in the repo.utils package and introduced a slimmer variant in o.s.d.util. Also, ReflectionUtils hosts now several methods that have been in ClassUtils along with an improved method naming (find vs. get in combination with return value semantics). CastUtils is deprecated as we do not widely use it.
1 parent 587cd70 commit 771347b

17 files changed

+320
-93
lines changed

src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
4949

5050
static {
5151

52-
CAUSE_FIELD = ReflectionUtils.findRequiredField(Throwable.class, "cause");
52+
CAUSE_FIELD = ReflectionUtils.getRequiredField(Throwable.class, "cause");
5353
ASSOCIATION_TYPE = ReflectionUtils.loadIfPresent("org.jmolecules.ddd.types.Association",
5454
AbstractPersistentProperty.class.getClassLoader());
5555
}

src/main/java/org/springframework/data/querydsl/binding/QuerydslPredicateBuilder.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ private static TypeDescriptor getTargetTypeDescriptor(PathInformation path) {
219219

220220
TypeDescriptor result = descriptor == null //
221221
? TypeDescriptor
222-
.nested(org.springframework.data.util.ReflectionUtils.findRequiredField(owningType, leafProperty), 0)
222+
.nested(org.springframework.data.util.ReflectionUtils.getRequiredField(owningType, leafProperty), 0)
223223
: TypeDescriptor
224224
.nested(new Property(owningType, descriptor.getReadMethod(), descriptor.getWriteMethod(), leafProperty), 0);
225225

src/main/java/org/springframework/data/repository/config/RepositoryComponentProvider.java

+12-7
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
import org.springframework.data.repository.NoRepositoryBean;
3434
import org.springframework.data.repository.Repository;
3535
import org.springframework.data.repository.RepositoryDefinition;
36-
import org.springframework.data.repository.util.ClassUtils;
3736
import org.springframework.lang.NonNull;
37+
import org.springframework.lang.Nullable;
3838
import org.springframework.util.Assert;
3939

4040
/**
@@ -103,7 +103,7 @@ public void addIncludeFilter(TypeFilter includeFilter) {
103103
@Override
104104
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
105105

106-
boolean isNonRepositoryInterface = !ClassUtils.isGenericRepositoryInterface(beanDefinition.getBeanClassName());
106+
boolean isNonRepositoryInterface = !isGenericRepositoryInterface(beanDefinition.getBeanClassName());
107107
boolean isTopLevelType = !beanDefinition.getMetadata().hasEnclosingClass();
108108
boolean isConsiderNestedRepositories = isConsiderNestedRepositoryInterfaces();
109109

@@ -150,6 +150,13 @@ public void setConsiderNestedRepositoryInterfaces(boolean considerNestedReposito
150150
this.considerNestedRepositoryInterfaces = considerNestedRepositoryInterfaces;
151151
}
152152

153+
/**
154+
* Returns whether the given type name is a {@link Repository} interface name.
155+
*/
156+
private static boolean isGenericRepositoryInterface(@Nullable String interfaceName) {
157+
return Repository.class.getName().equals(interfaceName);
158+
}
159+
153160
/**
154161
* {@link org.springframework.core.type.filter.TypeFilter} that only matches interfaces. Thus setting this up makes
155162
* only sense providing an interface type as {@code targetType}.
@@ -180,21 +187,19 @@ public boolean match(MetadataReader metadataReader, MetadataReaderFactory metada
180187
*
181188
* @author Oliver Gierke
182189
*/
183-
private static class AllTypeFilter implements TypeFilter {
184-
185-
private final List<TypeFilter> delegates;
190+
private record AllTypeFilter(List<TypeFilter> delegates) implements TypeFilter {
186191

187192
/**
188193
* Creates a new {@link AllTypeFilter} to match if all the given delegates match.
189194
*
190195
* @param delegates must not be {@literal null}.
191196
*/
192-
public AllTypeFilter(List<TypeFilter> delegates) {
197+
private AllTypeFilter {
193198

194199
Assert.notNull(delegates, "TypeFilter deleages must not be null");
195-
this.delegates = delegates;
196200
}
197201

202+
@Override
198203
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
199204
throws IOException {
200205

src/main/java/org/springframework/data/repository/config/RepositoryConfigurationDelegate.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.apache.commons.logging.Log;
2828
import org.apache.commons.logging.LogFactory;
29+
2930
import org.springframework.beans.factory.config.BeanDefinition;
3031
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
3132
import org.springframework.beans.factory.config.DependencyDescriptor;
@@ -51,10 +52,9 @@
5152
import org.springframework.data.repository.core.support.AbstractRepositoryMetadata;
5253
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
5354
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
54-
import org.springframework.data.util.ReflectionUtils;
55+
import org.springframework.data.util.ClassUtils;
5556
import org.springframework.lang.Nullable;
5657
import org.springframework.util.Assert;
57-
import org.springframework.util.ClassUtils;
5858
import org.springframework.util.StopWatch;
5959

6060
/**
@@ -123,8 +123,7 @@ private static Environment defaultEnvironment(@Nullable Environment environment,
123123
return environment;
124124
}
125125

126-
return resourceLoader instanceof EnvironmentCapable capable ? capable.getEnvironment()
127-
: new StandardEnvironment();
126+
return resourceLoader instanceof EnvironmentCapable capable ? capable.getEnvironment() : new StandardEnvironment();
128127
}
129128

130129
/**
@@ -321,19 +320,19 @@ private static ApplicationStartup getStartup(BeanDefinitionRegistry registry) {
321320
private ResolvableType getRepositoryFactoryBeanType(RepositoryConfiguration<?> configuration) {
322321

323322
String interfaceName = configuration.getRepositoryInterface();
324-
ClassLoader classLoader = resourceLoader.getClassLoader() == null ? ClassUtils.getDefaultClassLoader()
323+
ClassLoader classLoader = resourceLoader.getClassLoader() == null
324+
? org.springframework.util.ClassUtils.getDefaultClassLoader()
325325
: resourceLoader.getClassLoader();
326326

327327
classLoader = classLoader != null ? classLoader : getClass().getClassLoader();
328328

329-
Class<?> repositoryInterface = ReflectionUtils.loadIfPresent(interfaceName, classLoader);
329+
Class<?> repositoryInterface = ClassUtils.loadIfPresent(interfaceName, classLoader);
330330

331331
if (repositoryInterface == null) {
332332
return null;
333333
}
334334

335-
Class<?> factoryBean = ReflectionUtils.loadIfPresent(configuration.getRepositoryFactoryBeanClassName(),
336-
classLoader);
335+
Class<?> factoryBean = ClassUtils.loadIfPresent(configuration.getRepositoryFactoryBeanClassName(), classLoader);
337336

338337
if (factoryBean == null) {
339338
return null;

src/main/java/org/springframework/data/repository/core/RepositoryInformationSupport.java

+26-4
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.repository.core;
1717

18-
import static org.springframework.data.repository.util.ClassUtils.*;
19-
2018
import java.lang.reflect.Method;
2119
import java.lang.reflect.Modifier;
2220
import java.util.Arrays;
@@ -25,9 +23,12 @@
2523

2624
import org.springframework.core.annotation.AnnotationUtils;
2725
import org.springframework.data.annotation.QueryAnnotation;
26+
import org.springframework.data.repository.Repository;
2827
import org.springframework.data.util.Lazy;
2928
import org.springframework.data.util.Streamable;
3029
import org.springframework.data.util.TypeInformation;
30+
import org.springframework.lang.Contract;
31+
import org.springframework.lang.Nullable;
3132
import org.springframework.util.Assert;
3233
import org.springframework.util.ClassUtils;
3334

@@ -166,8 +167,8 @@ private final DefaultQueryMethods calculateQueryMethods() {
166167
Class<?> repositoryInterface = getRepositoryInterface();
167168

168169
return new DefaultQueryMethods(Streamable.of(Arrays.stream(repositoryInterface.getMethods())
169-
.map(it -> ClassUtils.getMostSpecificMethod(it, repositoryInterface))
170-
.filter(this::isQueryMethodCandidate)
170+
.map(it -> ClassUtils.getMostSpecificMethod(it, repositoryInterface)) //
171+
.filter(this::isQueryMethodCandidate) //
171172
.toList()), calculateHasCustomMethod(repositoryInterface));
172173
}
173174

@@ -187,6 +188,27 @@ private final boolean calculateHasCustomMethod(Class<?> repositoryInterface) {
187188
return false;
188189
}
189190

191+
/**
192+
* Returns where the given type is the {@link Repository} interface.
193+
*
194+
* @param ifc
195+
* @return
196+
*/
197+
private static boolean isGenericRepositoryInterface(Class<?> ifc) {
198+
return Repository.class.equals(ifc);
199+
}
200+
201+
/**
202+
* Returns whether the given type name is a repository interface name.
203+
*
204+
* @param interfaceName
205+
* @return
206+
*/
207+
@Contract("null -> false")
208+
public static boolean isGenericRepositoryInterface(@Nullable String interfaceName) {
209+
return Repository.class.getName().equals(interfaceName);
210+
}
211+
190212
/**
191213
* Information about query methods to allow canonical computation and reuse of that information.
192214
*

src/main/java/org/springframework/data/repository/core/support/QueryExecutionResultHandler.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import org.springframework.core.convert.ConversionService;
2828
import org.springframework.core.convert.TypeDescriptor;
2929
import org.springframework.core.convert.support.GenericConversionService;
30-
import org.springframework.data.repository.util.ClassUtils;
3130
import org.springframework.data.repository.util.QueryExecutionConverters;
3231
import org.springframework.data.repository.util.ReactiveWrapperConverters;
3332
import org.springframework.data.util.NullableWrapper;
@@ -67,7 +66,8 @@ class QueryExecutionResultHandler {
6766
public static <T> Class<T> loadIfPresent(String type) {
6867

6968
try {
70-
return (Class<T>) org.springframework.util.ClassUtils.forName(type, ClassUtils.class.getClassLoader());
69+
return (Class<T>) org.springframework.util.ClassUtils.forName(type,
70+
QueryExecutionResultHandler.class.getClassLoader());
7171
} catch (ClassNotFoundException | LinkageError e) {
7272
return null;
7373
}

src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java

+17-15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.Serializable;
1919
import java.lang.reflect.Constructor;
20+
import java.lang.reflect.InvocationTargetException;
2021
import java.lang.reflect.Method;
2122
import java.util.ArrayList;
2223
import java.util.Arrays;
@@ -184,7 +185,7 @@ public void setNamedQueries(@Nullable NamedQueries namedQueries) {
184185

185186
@Override
186187
public void setBeanClassLoader(@Nullable ClassLoader classLoader) {
187-
this.classLoader = classLoader == null ? org.springframework.util.ClassUtils.getDefaultClassLoader() : classLoader;
188+
this.classLoader = classLoader == null ? ClassUtils.getDefaultClassLoader() : classLoader;
188189
this.projectionFactory = createProjectionFactory();
189190
}
190191

@@ -429,15 +430,15 @@ public <T> T getRepository(Class<T> repositoryInterface, RepositoryFragments fra
429430

430431
if (DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(repositoryInterface)) {
431432
if (logger.isTraceEnabled()) {
432-
logger.trace(LogMessage.format("Register DefaultMethodInvokingMethodInterceptor for %s…", repositoryInterface.getName()));
433+
logger.trace(LogMessage.format("Register DefaultMethodInvokingMethodInterceptor for %s…",
434+
repositoryInterface.getName()));
433435
}
434436
result.addAdvice(new DefaultMethodInvokingMethodInterceptor());
435437
}
436438

437439
Optional<QueryLookupStrategy> queryLookupStrategy = getQueryLookupStrategy(queryLookupStrategyKey,
438440
new ValueExpressionDelegate(
439-
new QueryMethodValueEvaluationContextAccessor(getEnvironment(), evaluationContextProvider),
440-
VALUE_PARSER));
441+
new QueryMethodValueEvaluationContextAccessor(getEnvironment(), evaluationContextProvider), VALUE_PARSER));
441442
result.addAdvice(new QueryExecutorMethodInterceptor(information, getProjectionFactory(), queryLookupStrategy,
442443
namedQueries, queryPostProcessors, methodInvocationListeners));
443444

@@ -529,7 +530,7 @@ private RepositoryInformation getRepositoryInformation(RepositoryMetadata metada
529530

530531
return repositoryInformationCache.computeIfAbsent(cacheKey, key -> {
531532

532-
Class<?> baseClass = repositoryBaseClass != null ? repositoryBaseClass : getRepositoryBaseClass(metadata);
533+
Class<?> baseClass = repositoryBaseClass != null ? repositoryBaseClass : getRepositoryBaseClass(metadata);
533534

534535
return new DefaultRepositoryInformation(metadata, baseClass, composition);
535536
});
@@ -751,11 +752,13 @@ public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) thro
751752

752753
try {
753754
return composition.invoke(invocationMulticaster, method, arguments);
754-
} catch (Exception e) {
755-
org.springframework.data.repository.util.ClassUtils.unwrapReflectionException(e);
756-
}
755+
} catch (Exception ex) {
756+
if (ex instanceof InvocationTargetException) {
757+
throw ((InvocationTargetException) ex).getTargetException();
758+
}
757759

758-
throw new IllegalStateException("Should not occur");
760+
throw ex;
761+
}
759762
}
760763
}
761764

@@ -886,25 +889,24 @@ static class RepositoryValidator {
886889

887890
static {
888891

889-
org.springframework.data.repository.util.ClassUtils.ifPresent(
890-
"org.springframework.data.querydsl.QuerydslPredicateExecutor", RepositoryValidator.class.getClassLoader(),
891-
it -> {
892+
org.springframework.data.util.ClassUtils.ifPresent("org.springframework.data.querydsl.QuerydslPredicateExecutor",
893+
RepositoryValidator.class.getClassLoader(), it -> {
892894
WELL_KNOWN_EXECUTORS.put(it, "Querydsl");
893895
});
894896

895-
org.springframework.data.repository.util.ClassUtils.ifPresent(
897+
org.springframework.data.util.ClassUtils.ifPresent(
896898
"org.springframework.data.querydsl.ReactiveQuerydslPredicateExecutor",
897899
RepositoryValidator.class.getClassLoader(), it -> {
898900
WELL_KNOWN_EXECUTORS.put(it, "Reactive Querydsl");
899901
});
900902

901-
org.springframework.data.repository.util.ClassUtils.ifPresent(
903+
org.springframework.data.util.ClassUtils.ifPresent(
902904
"org.springframework.data.repository.query.QueryByExampleExecutor",
903905
RepositoryValidator.class.getClassLoader(), it -> {
904906
WELL_KNOWN_EXECUTORS.put(it, "Query by Example");
905907
});
906908

907-
org.springframework.data.repository.util.ClassUtils.ifPresent(
909+
org.springframework.data.util.ClassUtils.ifPresent(
908910
"org.springframework.data.repository.query.ReactiveQueryByExampleExecutor",
909911
RepositoryValidator.class.getClassLoader(), it -> {
910912
WELL_KNOWN_EXECUTORS.put(it, "Reactive Query by Example");

src/main/java/org/springframework/data/repository/query/Parameter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
import org.springframework.data.domain.Pageable;
3131
import org.springframework.data.domain.ScrollPosition;
3232
import org.springframework.data.domain.Sort;
33-
import org.springframework.data.repository.util.ClassUtils;
3433
import org.springframework.data.repository.util.QueryExecutionConverters;
3534
import org.springframework.data.repository.util.ReactiveWrapperConverters;
35+
import org.springframework.data.util.ClassUtils;
3636
import org.springframework.data.util.Lazy;
3737
import org.springframework.data.util.TypeInformation;
3838
import org.springframework.util.Assert;

src/main/java/org/springframework/data/repository/query/QueryMethod.java

+10-8
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@
1515
*/
1616
package org.springframework.data.repository.query;
1717

18-
import static org.springframework.data.repository.util.ClassUtils.*;
19-
2018
import java.lang.reflect.Method;
2119
import java.util.Collections;
2220
import java.util.Set;
@@ -38,6 +36,7 @@
3836
import org.springframework.data.util.Lazy;
3937
import org.springframework.data.util.NullableWrapperConverters;
4038
import org.springframework.data.util.ReactiveWrappers;
39+
import org.springframework.data.util.ReflectionUtils;
4140
import org.springframework.data.util.TypeInformation;
4241
import org.springframework.util.Assert;
4342

@@ -77,7 +76,9 @@ public QueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory
7776
Assert.notNull(factory, "ProjectionFactory must not be null");
7877

7978
Parameters.TYPES.stream() //
80-
.filter(type -> getNumberOfOccurrences(method, type) > 1).findFirst().ifPresent(type -> {
79+
.filter(type -> ReflectionUtils.getParameterCount(method, type::equals) > 1) //
80+
.findFirst() //
81+
.ifPresent(type -> {
8182
throw new IllegalStateException(String.format(
8283
"Method must have only one argument of type %s; Offending method: %s", type.getSimpleName(), method));
8384
});
@@ -107,19 +108,19 @@ private void validate() {
107108

108109
QueryMethodValidator.validate(method);
109110

110-
if (hasParameterOfType(method, Pageable.class)) {
111+
if (ReflectionUtils.hasParameterOfType(method, Pageable.class)) {
111112

112113
if (!isStreamQuery()) {
113114
assertReturnTypeAssignable(method, QueryExecutionConverters.getAllowedPageableTypes());
114115
}
115116

116-
if (hasParameterOfType(method, Sort.class)) {
117+
if (ReflectionUtils.hasParameterOfType(method, Sort.class)) {
117118
throw new IllegalStateException(String.format("Method must not have Pageable *and* Sort parameters. "
118119
+ "Use sorting capabilities on Pageable instead; Offending method: %s", method));
119120
}
120121
}
121122

122-
if (hasParameterOfType(method, ScrollPosition.class)) {
123+
if (ReflectionUtils.hasParameterOfType(method, ScrollPosition.class)) {
123124
assertReturnTypeAssignable(method, Collections.singleton(Window.class));
124125
}
125126

@@ -388,11 +389,12 @@ static void validate(Method method) {
388389

389390
static Predicate<Method> pageableCannotHaveSortOrLimit = (method) -> {
390391

391-
if (!hasParameterAssignableToType(method, Pageable.class)) {
392+
if (!ReflectionUtils.hasParameterAssignableToType(method, Pageable.class)) {
392393
return true;
393394
}
394395

395-
if (hasParameterAssignableToType(method, Sort.class) || hasParameterAssignableToType(method, Limit.class)) {
396+
if (ReflectionUtils.hasParameterAssignableToType(method, Sort.class)
397+
|| ReflectionUtils.hasParameterAssignableToType(method, Limit.class)) {
396398
return false;
397399
}
398400

0 commit comments

Comments
 (0)