Merge branch '6.2.x'
This commit is contained in:
commit
64de254b58
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.aop.aspectj;
|
||||
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
@ -67,7 +68,7 @@ public class SimpleAspectInstanceFactory implements AspectInstanceFactory {
|
|||
throw new AopConfigException(
|
||||
"Unable to instantiate aspect class: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new AopConfigException(
|
||||
"Could not access aspect constructor: " + this.aspectClass.getName(), ex);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.aop.support;
|
||||
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
@ -366,7 +367,7 @@ public abstract class AopUtils {
|
|||
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
|
||||
method + "] on target [" + target + "]", ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new AopInvocationException("Could not access method [" + method + "]", ex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.beans;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -142,7 +143,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
|||
ReflectionUtils.makeAccessible(this.field);
|
||||
return this.field.get(getWrappedInstance());
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new InvalidPropertyException(getWrappedClass(),
|
||||
this.field.getName(), "Field is not accessible", ex);
|
||||
}
|
||||
|
@ -154,7 +155,7 @@ public class DirectFieldAccessor extends AbstractNestablePropertyAccessor {
|
|||
ReflectionUtils.makeAccessible(this.field);
|
||||
this.field.set(getWrappedInstance(), value);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new InvalidPropertyException(getWrappedClass(), this.field.getName(),
|
||||
"Field is not accessible", ex);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.beans.factory.support;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -167,7 +168,7 @@ public class SimpleInstantiationStrategy implements InstantiationStrategy {
|
|||
"Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
|
||||
"args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new BeanInstantiationException(factoryMethod,
|
||||
"Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.context.event;
|
||||
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
@ -366,8 +367,8 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
|||
return null;
|
||||
}
|
||||
|
||||
ReflectionUtils.makeAccessible(this.method);
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(this.method);
|
||||
if (KotlinDetector.isSuspendingFunction(this.method)) {
|
||||
return CoroutinesUtils.invokeSuspendingFunction(this.method, bean, args);
|
||||
}
|
||||
|
@ -377,7 +378,7 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
|
|||
assertTargetBean(this.method, bean, args);
|
||||
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new IllegalStateException(getInvocationErrorMessage(bean, ex.getMessage(), args), ex);
|
||||
}
|
||||
catch (InvocationTargetException ex) {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.scheduling.annotation;
|
||||
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
@ -173,7 +174,7 @@ abstract class ScheduledAnnotationReactiveSupport {
|
|||
"Cannot obtain a Publisher-convertible value from the @Scheduled reactive method",
|
||||
ex.getTargetException());
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new IllegalArgumentException(
|
||||
"Cannot obtain a Publisher-convertible value from the @Scheduled reactive method", ex);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.scripting.groovy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
@ -331,7 +332,7 @@ public class GroovyScriptFactory implements ScriptFactory, BeanFactoryAware, Bea
|
|||
throw new ScriptCompilationException(
|
||||
scriptSource, "Unable to instantiate Groovy script class: " + scriptClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new ScriptCompilationException(
|
||||
scriptSource, "Could not access Groovy script constructor: " + scriptClass.getName(), ex);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.scripting.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
import javax.script.Invocable;
|
||||
|
@ -167,7 +168,7 @@ public class StandardScriptFactory implements ScriptFactory, BeanClassLoaderAwar
|
|||
throw new ScriptCompilationException(
|
||||
scriptSource, "Unable to instantiate script class: " + scriptClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new ScriptCompilationException(
|
||||
scriptSource, "Could not access script constructor: " + scriptClass.getName(), ex);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.springframework.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
|
@ -305,7 +306,7 @@ public class AutoPopulatingList<E> implements List<E>, Serializable {
|
|||
throw new ElementInstantiationException(
|
||||
"Unable to instantiate element class: " + this.elementClass.getName(), ex);
|
||||
}
|
||||
catch (IllegalAccessException ex) {
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
throw new ElementInstantiationException(
|
||||
"Could not access element constructor: " + this.elementClass.getName(), ex);
|
||||
}
|
||||
|
|
|
@ -1466,10 +1466,8 @@ public abstract class ClassUtils {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get the first publicly accessible method in the supplied method's type hierarchy that
|
||||
* Get the highest publicly accessible method in the supplied method's type hierarchy that
|
||||
* has a method signature equivalent to the supplied method, if possible.
|
||||
* <p>If the supplied method is {@code public} and declared in a {@code public} type,
|
||||
* the supplied method will be returned.
|
||||
* <p>Otherwise, this method recursively searches the class hierarchy and implemented
|
||||
* interfaces for an equivalent method that is {@code public} and declared in a
|
||||
* {@code public} type.
|
||||
|
@ -1492,19 +1490,23 @@ public abstract class ClassUtils {
|
|||
* @see #getMostSpecificMethod(Method, Class)
|
||||
*/
|
||||
public static Method getPubliclyAccessibleMethodIfPossible(Method method, @Nullable Class<?> targetClass) {
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
// If the method is not public, we can abort the search immediately; or if the method's
|
||||
// declaring class is public, the method is already publicly accessible.
|
||||
if (!Modifier.isPublic(method.getModifiers()) || Modifier.isPublic(declaringClass.getModifiers())) {
|
||||
// If the method is not public, we can abort the search immediately.
|
||||
if (!Modifier.isPublic(method.getModifiers())) {
|
||||
return method;
|
||||
}
|
||||
|
||||
Method interfaceMethod = getInterfaceMethodIfPossible(method, targetClass, true);
|
||||
// If we found a method in a public interface, return the interface method.
|
||||
if (!interfaceMethod.equals(method)) {
|
||||
if (interfaceMethod != method) {
|
||||
return interfaceMethod;
|
||||
}
|
||||
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
// Bypass cache for java.lang.Object unless it is actually an overridable method declared there.
|
||||
if (declaringClass.getSuperclass() == Object.class && !ReflectionUtils.isObjectMethod(method)) {
|
||||
return method;
|
||||
}
|
||||
|
||||
Method result = publiclyAccessibleMethodCache.computeIfAbsent(method,
|
||||
key -> findPubliclyAccessibleMethodIfPossible(key.getName(), key.getParameterTypes(), declaringClass));
|
||||
return (result != null ? result : method);
|
||||
|
@ -1513,19 +1515,19 @@ public abstract class ClassUtils {
|
|||
private static @Nullable Method findPubliclyAccessibleMethodIfPossible(
|
||||
String methodName, Class<?>[] parameterTypes, Class<?> declaringClass) {
|
||||
|
||||
Method result = null;
|
||||
Class<?> current = declaringClass.getSuperclass();
|
||||
while (current != null) {
|
||||
if (Modifier.isPublic(current.getModifiers())) {
|
||||
try {
|
||||
return current.getDeclaredMethod(methodName, parameterTypes);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
// ignore
|
||||
}
|
||||
Method method = getMethodOrNull(current, methodName, parameterTypes);
|
||||
if (method == null) {
|
||||
break;
|
||||
}
|
||||
current = current.getSuperclass();
|
||||
if (Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
|
||||
result = method;
|
||||
}
|
||||
current = method.getDeclaringClass().getSuperclass();
|
||||
}
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.util;
|
||||
|
||||
import java.lang.reflect.InaccessibleObjectException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
@ -169,7 +170,8 @@ public class MethodInvoker {
|
|||
@Nullable Object[] arguments = getArguments();
|
||||
Class<?>[] argTypes = new Class<?>[arguments.length];
|
||||
for (int i = 0; i < arguments.length; ++i) {
|
||||
argTypes[i] = (arguments[i] != null ? arguments[i].getClass() : Object.class);
|
||||
Object argument = arguments[i];
|
||||
argTypes[i] = (argument != null ? argument.getClass() : Object.class);
|
||||
}
|
||||
|
||||
// Try to get the exact method first.
|
||||
|
@ -268,8 +270,20 @@ public class MethodInvoker {
|
|||
if (targetObject == null && !Modifier.isStatic(preparedMethod.getModifiers())) {
|
||||
throw new IllegalArgumentException("Target method must not be non-static without a target");
|
||||
}
|
||||
ReflectionUtils.makeAccessible(preparedMethod);
|
||||
return preparedMethod.invoke(targetObject, getArguments());
|
||||
try {
|
||||
ReflectionUtils.makeAccessible(preparedMethod);
|
||||
return preparedMethod.invoke(targetObject, getArguments());
|
||||
}
|
||||
catch (IllegalAccessException | InaccessibleObjectException ex) {
|
||||
if (targetObject != null) {
|
||||
Method fallbackMethod =
|
||||
ClassUtils.getPubliclyAccessibleMethodIfPossible(preparedMethod, targetObject.getClass());
|
||||
if (fallbackMethod != preparedMethod) {
|
||||
return fallbackMethod.invoke(targetObject, getArguments());
|
||||
}
|
||||
}
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -296,12 +310,13 @@ public class MethodInvoker {
|
|||
public static int getTypeDifferenceWeight(Class<?>[] paramTypes, @Nullable Object[] args) {
|
||||
int result = 0;
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
if (!ClassUtils.isAssignableValue(paramTypes[i], args[i])) {
|
||||
Class<?> paramType = paramTypes[i];
|
||||
Object arg = args[i];
|
||||
if (!ClassUtils.isAssignableValue(paramType, arg)) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
if (args[i] != null) {
|
||||
Class<?> paramType = paramTypes[i];
|
||||
Class<?> superClass = args[i].getClass().getSuperclass();
|
||||
if (arg != null) {
|
||||
Class<?> superClass = arg.getClass().getSuperclass();
|
||||
while (superClass != null) {
|
||||
if (paramType.equals(superClass)) {
|
||||
result = result + 2;
|
||||
|
|
|
@ -687,13 +687,13 @@ class ClassUtilsTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void publicMethodInPublicClass() throws Exception {
|
||||
void publicMethodInObjectClass() throws Exception {
|
||||
Class<?> originalType = String.class;
|
||||
Method originalMethod = originalType.getDeclaredMethod("toString");
|
||||
Method originalMethod = originalType.getDeclaredMethod("hashCode");
|
||||
|
||||
Method publiclyAccessibleMethod = ClassUtils.getPubliclyAccessibleMethodIfPossible(originalMethod, null);
|
||||
assertThat(publiclyAccessibleMethod.getDeclaringClass()).isEqualTo(originalType);
|
||||
assertThat(publiclyAccessibleMethod).isSameAs(originalMethod);
|
||||
assertThat(publiclyAccessibleMethod.getDeclaringClass()).isEqualTo(Object.class);
|
||||
assertThat(publiclyAccessibleMethod.getName()).isEqualTo("hashCode");
|
||||
assertPubliclyAccessible(publiclyAccessibleMethod);
|
||||
}
|
||||
|
||||
|
@ -703,9 +703,9 @@ class ClassUtilsTests {
|
|||
Method originalMethod = originalType.getDeclaredMethod("size");
|
||||
|
||||
Method publiclyAccessibleMethod = ClassUtils.getPubliclyAccessibleMethodIfPossible(originalMethod, null);
|
||||
// Should not find the interface method in List.
|
||||
assertThat(publiclyAccessibleMethod.getDeclaringClass()).isEqualTo(originalType);
|
||||
assertThat(publiclyAccessibleMethod).isSameAs(originalMethod);
|
||||
// Should find the interface method in List.
|
||||
assertThat(publiclyAccessibleMethod.getDeclaringClass()).isEqualTo(List.class);
|
||||
assertThat(publiclyAccessibleMethod.getName()).isEqualTo("size");
|
||||
assertPubliclyAccessible(publiclyAccessibleMethod);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
package org.springframework.test.context.bean.override.convention;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -59,7 +58,7 @@ final class TestBeanOverrideHandler extends BeanOverrideHandler {
|
|||
ReflectionUtils.makeAccessible(this.factoryMethod);
|
||||
return this.factoryMethod.invoke(null);
|
||||
}
|
||||
catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
catch (Throwable ex) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to invoke @TestBean factory method: " + this.factoryMethod, ex);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue