DATACMNS-991 - Support Java 9 compatible MethodHandle lookup.
DefaultMethodInvokingMethodInterceptor now contains two alternative implementations, one compatible to Java 8, one for Java 9. Original pull request: #223.
This commit is contained in:
committed by
Mark Paluch
parent
77be0ba859
commit
6a39937d51
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2017 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.
|
||||
@@ -15,7 +15,10 @@
|
||||
*/
|
||||
package org.springframework.data.projection;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -27,6 +30,7 @@ import org.springframework.aop.ProxyMethodInvocation;
|
||||
* Method interceptor to invoke default methods on the repository proxy.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Jens Schauder
|
||||
*/
|
||||
public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
@@ -36,15 +40,27 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor
|
||||
* Creates a new {@link DefaultMethodInvokingMethodInterceptor}.
|
||||
*/
|
||||
public DefaultMethodInvokingMethodInterceptor() {
|
||||
constructor = tryToGetLookupConstructor();
|
||||
}
|
||||
|
||||
private static Constructor<Lookup> tryToGetLookupConstructor() {
|
||||
|
||||
try {
|
||||
this.constructor = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class);
|
||||
|
||||
if (!constructor.isAccessible()) {
|
||||
constructor.setAccessible(true);
|
||||
Constructor<Lookup> accessibleConstructor = Lookup.class.getDeclaredConstructor(Class.class);
|
||||
|
||||
if (!accessibleConstructor.isAccessible()) {
|
||||
accessibleConstructor.setAccessible(true);
|
||||
}
|
||||
|
||||
return accessibleConstructor;
|
||||
} catch (Exception ex) {
|
||||
// this is the signal that we are on Java 9 and can't use the accessible constructor approach.
|
||||
if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
|
||||
return null;
|
||||
} else {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
} catch (Exception o_O) {
|
||||
throw new IllegalStateException(o_O);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +81,24 @@ public class DefaultMethodInvokingMethodInterceptor implements MethodInterceptor
|
||||
Class<?> declaringClass = method.getDeclaringClass();
|
||||
Object proxy = ((ProxyMethodInvocation) invocation).getProxy();
|
||||
|
||||
return constructor.newInstance(declaringClass).unreflectSpecial(method, declaringClass).bindTo(proxy)
|
||||
.invokeWithArguments(arguments);
|
||||
return getMethodHandle(method, arguments, declaringClass, proxy).bindTo(proxy).invokeWithArguments(arguments);
|
||||
}
|
||||
|
||||
private MethodHandle getMethodHandle(Method method, Object[] arguments, Class<?> declaringClass, Object proxy)
|
||||
throws Throwable {
|
||||
|
||||
if (constructor != null) {
|
||||
// java 8 variant
|
||||
return constructor.newInstance(declaringClass).unreflectSpecial(method, declaringClass);
|
||||
}
|
||||
|
||||
// java 9 variant
|
||||
return MethodHandles.lookup() //
|
||||
.findSpecial( //
|
||||
method.getDeclaringClass(), //
|
||||
method.getName(), //
|
||||
MethodType.methodType(method.getReturnType(), method.getParameterTypes()), //
|
||||
method.getDeclaringClass() //
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user