MethodInvocationRecorder now supports traversing primitive properties.

We now return a default value for invocations of methods returning a primitive value to pass the AOP infrastructure's check for compatible values. Before, that barked at the null value returned for the invocation.

Fixes #2612.
This commit is contained in:
Oliver Drotbohm
2022-05-04 14:57:45 +02:00
parent d4c8dfe518
commit cd4ecf4f00
2 changed files with 19 additions and 5 deletions

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.util;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
@@ -158,7 +159,7 @@ public class MethodInvocationRecorder {
private InvocationInformation registerInvocation(Method method, Class<?> proxyType) {
Recorded<?> create = Modifier.isFinal(proxyType.getModifiers()) ? new Unrecorded() : create(proxyType);
Recorded<?> create = Modifier.isFinal(proxyType.getModifiers()) ? new Unrecorded(proxyType) : create(proxyType);
InvocationInformation information = new InvocationInformation(create, method);
return this.information = information;
@@ -167,7 +168,7 @@ public class MethodInvocationRecorder {
private static final class InvocationInformation {
private static final InvocationInformation NOT_INVOKED = new InvocationInformation(new Unrecorded(), null);
private static final InvocationInformation NOT_INVOKED = new InvocationInformation(new Unrecorded(null), null);
private final Recorded<?> recorded;
private final @Nullable Method invokedMethod;
@@ -251,7 +252,7 @@ public class MethodInvocationRecorder {
int result = ObjectUtils.nullSafeHashCode(recorded);
result = 31 * result + ObjectUtils.nullSafeHashCode(invokedMethod);
result = (31 * result) + ObjectUtils.nullSafeHashCode(invokedMethod);
return result;
}
@@ -386,8 +387,8 @@ public class MethodInvocationRecorder {
static class Unrecorded extends Recorded<Object> {
private Unrecorded() {
super(null, null);
private Unrecorded(@Nullable Class<?> type) {
super(type == null ? null : type.isPrimitive() ? getDefaultValue(type) : null, null);
}
/*
@@ -398,5 +399,9 @@ public class MethodInvocationRecorder {
public Optional<String> getPropertyPath(List<PropertyNameDetectionStrategy> strategies) {
return Optional.empty();
}
private static Object getDefaultValue(Class<?> clazz) {
return Array.get(Array.newInstance(clazz, 1), 0);
}
}
}

View File

@@ -86,6 +86,14 @@ class MethodInvocationRecorderUnitTests {
assertThat(recorder.record(Sample::getName).getPropertyPath()).hasValue("name");
}
@Test // #2612
void registersLookupForPrimitiveValue() {
Recorded<Foo> recorder = MethodInvocationRecorder.forProxyOf(Foo.class);
assertThat(recorder.record(Foo::getAge).getPropertyPath()).hasValue("age");
}
static final class FinalType {}
@Getter
@@ -93,6 +101,7 @@ class MethodInvocationRecorderUnitTests {
Bar bar;
Collection<Bar> bars;
String name;
int age;
}
@Getter