Skip to content

Commit

Permalink
Resolve bridged method when projected PropertyDescriptor resolves to …
Browse files Browse the repository at this point in the history
…a bridge method.

We now skip synthetic bridge methods when resolving a PropertyDescriptor from a called interface method on the target type and resolve the bridged method.

Closes #3697
  • Loading branch information
mp911de committed Dec 2, 2024
1 parent 00409b3 commit 2c56532
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.core.BridgeMethodResolver;
import org.springframework.data.util.DirectFieldAccessFallbackBeanWrapper;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
Expand Down Expand Up @@ -63,7 +65,8 @@ public Object invoke(@SuppressWarnings("null") MethodInvocation invocation) thro
PropertyDescriptor descriptor = BeanUtils.findPropertyForMethod(method);

if (descriptor == null) {
throw new IllegalStateException("Invoked method is not a property accessor");
throw new IllegalStateException("Invoked method '%s' is not a property accessor on '%s'"
.formatted(invocation.getMethod(), target.getWrappedClass().getName()));
}

if (!isSetterMethod(method, descriptor)) {
Expand All @@ -84,9 +87,14 @@ private static boolean isSetterMethod(Method method, PropertyDescriptor descript

private static Method lookupTargetMethod(MethodInvocation invocation, Class<?> targetType) {

Method method = BeanUtils.findMethod(targetType, invocation.getMethod().getName(),
invocation.getMethod().getParameterTypes());
Method invokedMethod = invocation.getMethod();
Method method = BeanUtils.findMethod(targetType, invokedMethod.getName(), invokedMethod.getParameterTypes());

if (method == null) {
return invokedMethod;
}

return method != null ? method : invocation.getMethod();
return BridgeMethodResolver.findBridgedMethod(method);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ void detectsKotlinPropertiesWithLeadingIsOnTargetType() throws Throwable {
assertThat(new PropertyAccessingMethodInterceptor(source).invoke(invocation)).isEqualTo(true);
}

@Test // GH-3697
void considersPropertyDescriptorsFromPackageProtectedSuperclass() throws Throwable {

var source = new SomeExposedClass();
source.setFirstname("Walter");

when(invocation.getMethod()).thenReturn(Projection.class.getMethod("getFirstname"));

Object result = new PropertyAccessingMethodInterceptor(source).invoke(invocation);

assertThat(result).isEqualTo(source.getFirstname());
}

static class Source {

String firstname;
Expand All @@ -138,4 +151,30 @@ interface Projection {

String someGarbage();
}

static class SomeBaseclass {

private String firstname;

public String getFirstname() {
return firstname;
}

public void setFirstname(String firstname) {
this.firstname = firstname;
}
}

public static class SomeExposedClass extends SomeBaseclass {

private String lastname;

public String getLastname() {
return lastname;
}

public void setLastname(String lastname) {
this.lastname = lastname;
}
}
}

0 comments on commit 2c56532

Please sign in to comment.