From 972449ef2d93a0f63d651cb34e57cef27bd48fc2 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 23 Jul 2019 10:48:06 +0200 Subject: [PATCH] DATACMNS-1556 - Limit default method invocation only to interfaces that actually declare default methods. --- ...efaultMethodInvokingMethodInterceptor.java | 21 +++++++++++++++++++ .../support/RepositoryFactorySupport.java | 6 ++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java b/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java index 34f7348e2..262aac6ba 100644 --- a/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java +++ b/src/main/java/org/springframework/data/projection/DefaultMethodInvokingMethodInterceptor.java @@ -26,6 +26,7 @@ import java.util.Map; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; + import org.springframework.aop.ProxyMethodInvocation; import org.springframework.data.util.Lazy; import org.springframework.lang.Nullable; @@ -45,6 +46,26 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor private final MethodHandleLookup methodHandleLookup = MethodHandleLookup.getMethodHandleLookup(); private final Map methodHandleCache = new ConcurrentReferenceHashMap<>(10, ReferenceType.WEAK); + /** + * Returns whether the {@code interfaceClass} declares {@link Method#isDefault() default methods}. + * + * @param interfaceClass the {@link Class} to inspect. + * @return {@literal true} if {@code interfaceClass} declares a default method. + * @since 2.2 + */ + public static boolean hasDefaultMethods(Class interfaceClass) { + + Method[] methods = ReflectionUtils.getAllDeclaredMethods(interfaceClass); + + for (Method method : methods) { + if (method.isDefault()) { + return true; + } + } + + return false; + } + /* * (non-Javadoc) * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) diff --git a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index c6e843310..54f84a2af 100644 --- a/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -35,6 +35,7 @@ import java.util.stream.Collectors; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; + import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.interceptor.ExposeInvocationInterceptor; import org.springframework.beans.BeanUtils; @@ -310,12 +311,13 @@ public abstract class RepositoryFactorySupport implements BeanClassLoaderAware, result.addAdvice(new MethodInvocationValidator()); } - result.addAdvice(SurroundingTransactionDetectorMethodInterceptor.INSTANCE); result.addAdvisor(ExposeInvocationInterceptor.ADVISOR); postProcessors.forEach(processor -> processor.postProcess(result, information)); - result.addAdvice(new DefaultMethodInvokingMethodInterceptor()); + if (DefaultMethodInvokingMethodInterceptor.hasDefaultMethods(repositoryInterface)) { + result.addAdvice(new DefaultMethodInvokingMethodInterceptor()); + } ProjectionFactory projectionFactory = getProjectionFactory(classLoader, beanFactory); result.addAdvice(new QueryExecutorMethodInterceptor(information, projectionFactory));