Remove @Deprecated API.

See #3208
This commit is contained in:
Mark Paluch
2024-11-20 13:58:58 +01:00
parent 3ef1bffb5c
commit 3417cb6dbb
9 changed files with 6 additions and 432 deletions

View File

@@ -27,6 +27,7 @@ import java.util.stream.Collectors;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.ClassUtils;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.ReflectionUtils;
@@ -50,7 +51,7 @@ public abstract class AbstractPersistentProperty<P extends PersistentProperty<P>
static {
CAUSE_FIELD = ReflectionUtils.getRequiredField(Throwable.class, "cause");
ASSOCIATION_TYPE = ReflectionUtils.loadIfPresent("org.jmolecules.ddd.types.Association",
ASSOCIATION_TYPE = ClassUtils.loadIfPresent("org.jmolecules.ddd.types.Association",
AbstractPersistentProperty.class.getClassLoader());
}

View File

@@ -37,9 +37,9 @@ import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.MappingException;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.ClassUtils;
import org.springframework.data.util.Lazy;
import org.springframework.data.util.Optionals;
import org.springframework.data.util.ReflectionUtils;
import org.springframework.data.util.StreamUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
@@ -316,7 +316,7 @@ public abstract class AnnotationBasedPersistentProperty<P extends PersistentProp
@SuppressWarnings("unchecked")
private static Class<? extends Annotation> loadIdentityType() {
return (Class<? extends Annotation>) ReflectionUtils.loadIfPresent("org.jmolecules.ddd.annotation.Identity",
return (Class<? extends Annotation>) ClassUtils.loadIfPresent("org.jmolecules.ddd.annotation.Identity",
AbstractPersistentProperty.class.getClassLoader());
}
}

View File

@@ -659,13 +659,11 @@ public abstract class RepositoryFactorySupport
*/
static class ImplementationMethodExecutionInterceptor implements MethodInterceptor {
private final RepositoryInformation information;
private final RepositoryComposition composition;
private final RepositoryInvocationMulticaster invocationMulticaster;
public ImplementationMethodExecutionInterceptor(RepositoryInformation information,
RepositoryComposition composition, List<RepositoryMethodInvocationListener> methodInvocationListeners) {
this.information = information;
this.composition = composition;
this.invocationMulticaster = methodInvocationListeners.isEmpty() ? NoOpRepositoryInvocationMulticaster.INSTANCE
: new DefaultRepositoryInvocationMulticaster(methodInvocationListeners);

View File

@@ -1,204 +0,0 @@
/*
* Copyright 2008-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Consumer;
import org.springframework.data.repository.Repository;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
/**
* Utility class to work with classes.
*
* @author Oliver Gierke
* @author Mark Paluch
* @author Johannes Englmeier
* @deprecated since 3.5, use {@link org.springframework.data.util.ClassUtils} instead.
*/
@Deprecated(since = "3.5", forRemoval = true)
public abstract class ClassUtils {
/**
* Private constructor to prevent instantiation.
*/
private ClassUtils() {}
/**
* Returns whether the given class contains a property with the given name.
*
* @param type
* @param property
* @return
*/
public static boolean hasProperty(Class<?> type, String property) {
if (null != ReflectionUtils.findMethod(type, "get" + property)) {
return true;
}
return null != ReflectionUtils.findField(type, StringUtils.uncapitalize(property));
}
/**
* Determine whether the {@link Class} identified by the supplied {@code className} is present * and can be loaded and
* call the {@link Consumer action} if the {@link Class} could be loaded.
*
* @param className the name of the class to check.
* @param classLoader the class loader to use.
* @param action the action callback to notify. (may be {@code null} which indicates the default class loader)
* @throws IllegalStateException if the corresponding class is resolvable but there was a readability mismatch in the
* inheritance hierarchy of the class (typically a missing dependency declaration in a Jigsaw module
* definition for a superclass or interface implemented by the class to be checked here)
*/
public static void ifPresent(String className, @Nullable ClassLoader classLoader, Consumer<Class<?>> action) {
org.springframework.data.util.ClassUtils.ifPresent(className, classLoader, action);
}
/**
* Returns wthere the given type is the {@link Repository} interface.
*
* @param interfaze
* @return
*/
public static boolean isGenericRepositoryInterface(Class<?> interfaze) {
return Repository.class.equals(interfaze);
}
/**
* Returns whether the given type name is a repository interface name.
*
* @param interfaceName
* @return
*/
public static boolean isGenericRepositoryInterface(@Nullable String interfaceName) {
return Repository.class.getName().equals(interfaceName);
}
/**
* @deprecated Use {@link #getNumberOfOccurrences(Method, Class)}.
*/
public static int getNumberOfOccurences(Method method, Class<?> type) {
return getNumberOfOccurrences(method, type);
}
/**
* Returns the number of occurrences for the given {@link Method#getParameterTypes() parameter type} in the given
* {@link Method}.
*
* @param method {@link Method} to evaluate.
* @param parameterType {@link Class} of the {@link Method} parameter type to count.
* @return the number of occurrences for the given {@link Method#getParameterTypes() parameter type} in the given
* {@link Method}.
* @see java.lang.reflect.Method#getParameterTypes()
*/
public static int getNumberOfOccurrences(@NonNull Method method, @NonNull Class<?> parameterType) {
return org.springframework.data.util.ReflectionUtils.getParameterCount(method, parameterType::equals);
}
/**
* Asserts the given {@link Method}'s return type to be one of the given types. Will unwrap known wrapper types before
* the assignment check (see {@link QueryExecutionConverters}).
*
* @param method must not be {@literal null}.
* @param types must not be {@literal null} or empty.
*/
public static void assertReturnTypeAssignable(Method method, Class<?>... types) {
Assert.notNull(method, "Method must not be null");
Assert.notEmpty(types, "Types must not be null or empty");
TypeInformation<?> returnType = getEffectivelyReturnedTypeFrom(method);
Arrays.stream(types)//
.filter(it -> it.isAssignableFrom(returnType.getType()))//
.findAny().orElseThrow(() -> new IllegalStateException(
"Method has to have one of the following return types: " + Arrays.toString(types)));
}
/**
* Returns whether the given object is of one of the given types. Will return {@literal false} for {@literal null}.
*
* @param object
* @param types
* @return
*/
public static boolean isOfType(@Nullable Object object, Collection<Class<?>> types) {
if (object == null) {
return false;
}
return types.stream().anyMatch(it -> it.isAssignableFrom(object.getClass()));
}
/**
* Returns whether the given {@link Method} has a parameter of the given type.
*
* @param method
* @param type
* @return
*/
public static boolean hasParameterOfType(Method method, Class<?> type) {
return org.springframework.data.util.ReflectionUtils.hasParameterOfType(method, type);
}
/**
* Returns whether the given {@link Method} has a parameter that is assignable to the given type.
*
* @param method
* @param type
* @return
*/
public static boolean hasParameterAssignableToType(Method method, Class<?> type) {
return org.springframework.data.util.ReflectionUtils.hasParameterOfType(method, type);
}
/**
* Helper method to extract the original exception that can possibly occur during a reflection call.
*
* @param ex
* @throws Throwable
*/
public static void unwrapReflectionException(Exception ex) throws Throwable {
if (ex instanceof InvocationTargetException ite) {
ReflectionUtils.handleInvocationTargetException(ite);
}
throw ex;
}
// TODO: we should also consider having the owning type here so we can resolve generics better.
private static TypeInformation<?> getEffectivelyReturnedTypeFrom(Method method) {
TypeInformation<?> returnType = TypeInformation.fromReturnTypeOf(method);
return QueryExecutionConverters.supports(returnType.getType()) //
|| ReactiveWrapperConverters.supports(returnType.getType()) //
? returnType.getRequiredComponentType() //
: returnType;
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright 2017-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.util;
/**
* @deprecated since 3.5 will be removed in a future release.
*/
@Deprecated(since = "3.5", forRemoval = true)
public interface CastUtils {
@SuppressWarnings("unchecked")
public static <T> T cast(Object object) {
return (T) object;
}
}

View File

@@ -28,7 +28,6 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.BeanUtils;
import org.springframework.core.KotlinDetector;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
@@ -98,27 +97,6 @@ public final class ReflectionUtils {
return (int) Arrays.stream(method.getParameterTypes()).filter(predicate).count();
}
/**
* Creates an instance of the class with the given fully qualified name or returns the given default instance if the
* class cannot be loaded or instantiated.
*
* @param classname the fully qualified class name to create an instance for.
* @param defaultInstance the instance to fall back to in case the given class cannot be loaded or instantiated.
* @return
* @deprecated since 3.5 as it is not used within the framework anymore.
*/
@SuppressWarnings("unchecked")
@Deprecated(since = "3.5", forRemoval = true)
public static <T> T createInstanceIfPresent(String classname, T defaultInstance) {
try {
Class<?> type = ClassUtils.forName(classname, ClassUtils.getDefaultClassLoader());
return (T) BeanUtils.instantiateClass(type);
} catch (Exception e) {
return defaultInstance;
}
}
/**
* Check whether the given {@code type} represents a void type such as {@code void}, {@link Void} or Kotlin
* {@code Unit}.
@@ -264,20 +242,6 @@ public final class ReflectionUtils {
return foundField;
}
/**
* Finds the field of the given name on the given type.
*
* @param type must not be {@literal null}.
* @param name must not be {@literal null} or empty.
* @return the required field.
* @throws IllegalArgumentException in case the field can't be found.
* @deprecated use {@link #getRequiredField(Class, String)} instead.
*/
@Deprecated(since = "3.5", forRemoval = true)
public static Field findRequiredField(Class<?> type, String name) {
return getRequiredField(type, name);
}
/**
* Obtains the required field of the given name on the given type or throws {@link IllegalArgumentException} if the
* found could not be found.
@@ -411,20 +375,6 @@ public final class ReflectionUtils {
return Stream.concat(returnType, parameterTypes);
}
/**
* Returns the {@link Method} with the given name and parameters declared on the given type, if available.
*
* @param type must not be {@literal null}.
* @param name must not be {@literal null} or empty.
* @param parameterTypes must not be {@literal null}.
* @return the optional Method.
* @since 2.0
*/
@Deprecated(since = "3.5", forRemoval = true)
public static Optional<Method> getMethod(Class<?> type, String name, ResolvableType... parameterTypes) {
return Optional.ofNullable(findMethod(type, name, parameterTypes));
}
/**
* Returns the {@link Method} with the given name and parameters declared on the given type, if available.
*
@@ -557,18 +507,4 @@ public final class ReflectionUtils {
throw new IllegalArgumentException(String.format("Primitive type %s not supported", type));
}
/**
* Loads the class with the given name using the given {@link ClassLoader}.
*
* @param name the name of the class to be loaded.
* @param classLoader the {@link ClassLoader} to use to load the class.
* @return the {@link Class} or {@literal null} in case the class can't be loaded for any reason.
* @since 2.5
*/
@Nullable
@Deprecated(since = "3.5", forRemoval = true)
public static Class<?> loadIfPresent(String name, ClassLoader classLoader) {
return org.springframework.data.util.ClassUtils.loadIfPresent(name, classLoader);
}
}

View File

@@ -28,7 +28,6 @@ import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.querydsl.binding.QuerydslBindingsFactory;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.data.querydsl.binding.QuerydslPredicateBuilder;
import org.springframework.data.util.CastUtils;
import org.springframework.data.util.TypeInformation;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -90,6 +89,7 @@ public abstract class QuerydslPredicateArgumentResolverSupport {
return false;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
Predicate getPredicate(MethodParameter parameter, MultiValueMap<String, String> queryParameters) {
MergedAnnotations annotations = MergedAnnotations.from(parameter.getParameter());
@@ -98,7 +98,7 @@ public abstract class QuerydslPredicateArgumentResolverSupport {
TypeInformation<?> domainType = extractTypeInfo(parameter, predicateAnnotation).getRequiredActualType();
Optional<Class<? extends QuerydslBinderCustomizer<?>>> bindingsAnnotation = predicateAnnotation.getValue("bindings") //
.map(CastUtils::cast);
.map(it -> (Class) it);
QuerydslBindings bindings = bindingsAnnotation //
.map(it -> bindingsFactory.createBindingsFor(domainType, it)) //

View File

@@ -27,7 +27,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.util.ClassUtils;
import org.springframework.data.util.TypeInformation;
/**
@@ -142,12 +141,6 @@ class DefaultRepositoryMetadataUnitTests {
}
/**
* Sample interface to serve two purposes:
* <ol>
* <li>Check that {@link ClassUtils#getDomainClass(Class)} skips non {@link GenericDao} interfaces</li>
* <li>Check that {@link ClassUtils#getDomainClass(Class)} traverses interface hierarchy</li>
* </ol>
*
* @author Oliver Gierke
*/
private interface SomeDao extends Serializable, UserRepository {

View File

@@ -1,122 +0,0 @@
/*
* Copyright 2008-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.repository.util;
import static org.assertj.core.api.Assertions.*;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.repository.Repository;
import org.springframework.scheduling.annotation.Async;
/**
* Unit tests for {@link ClassUtils}.
*
* @author Oliver Gierke
* @author John Blum
*/
class ClassUtilsUnitTests {
@Test
void rejectsInvalidReturnType() {
assertThatIllegalStateException().isThrownBy(() -> ClassUtils.assertReturnTypeAssignable(
SomeDao.class.getMethod("findByFirstname", Pageable.class, String.class), User.class));
}
@Test
void determinesValidFieldsCorrectly() {
assertThat(ClassUtils.hasProperty(User.class, "firstname")).isTrue();
assertThat(ClassUtils.hasProperty(User.class, "Firstname")).isTrue();
assertThat(ClassUtils.hasProperty(User.class, "address")).isFalse();
}
@Test // DATACMNS-769
void unwrapsWrapperTypesBeforeAssignmentCheck() throws Exception {
ClassUtils.assertReturnTypeAssignable(UserRepository.class.getMethod("findAsync", Pageable.class),
Page.class);
}
@Test
public void numberOfOccurrencesForMultipleMethodParametersOfType() throws Exception {
Method findByAddress = AnotherDao.class.getMethod("findByAddress", Pageable.class, Pageable.class);
assertThat(ClassUtils.getNumberOfOccurrences(findByAddress, Pageable.class)).isEqualTo(2);
}
@Test
public void numberOfOccurrencesForNoMethodParameterOfType() throws Exception {
Method findByAddress = AnotherDao.class.getMethod("findByAddress", Pageable.class, Pageable.class);
assertThat(ClassUtils.getNumberOfOccurrences(findByAddress, Sort.class)).isZero();
assertThat(ClassUtils.getNumberOfOccurrences(findByAddress, Page.class)).isZero();
}
@Test
public void numberOfOccurrencesForSingleMethodParameterOfType() throws Exception {
Method findByFirstname = SomeDao.class.getMethod("findByFirstname", Pageable.class, String.class);
assertThat(ClassUtils.getNumberOfOccurrences(findByFirstname, Pageable.class)).isOne();
assertThat(ClassUtils.getNumberOfOccurrences(findByFirstname, String.class)).isOne();
}
@SuppressWarnings("unused")
private class User {
private String firstname;
String getAddress() {
return null;
}
}
interface UserRepository extends Repository<User, Integer> {
@Async
Future<Page<User>> findAsync(Pageable pageable);
}
interface SomeDao extends Serializable, UserRepository {
Page<User> findByFirstname(Pageable pageable, String firstname);
GenericType<User> someMethod();
List<Map<String, Object>> anotherMethod();
}
interface AnotherDao extends Repository<User, Integer> {
Page<User> findByAddress(Pageable pageableOne, Pageable pageableTwo);
}
class GenericType<T> {
}
}