Browse Source

Sets method access for hystrix package-private fallback method

For interfaces with package-private access, hystrix fallback calls would
fail. This sets these methods accessible, caching to reduce reflection.

Fixes #353
pull/367/merge
liuzhengyang 9 years ago committed by Adrian Cole
parent
commit
2ef3bc80c3
  1. 23
      hystrix/src/main/java/feign/hystrix/HystrixInvocationHandler.java

23
hystrix/src/main/java/feign/hystrix/HystrixInvocationHandler.java

@ -22,6 +22,7 @@ import com.netflix.hystrix.HystrixCommandKey; @@ -22,6 +22,7 @@ import com.netflix.hystrix.HystrixCommandKey;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import feign.InvocationHandlerFactory;
@ -29,7 +30,6 @@ import feign.InvocationHandlerFactory.MethodHandler; @@ -29,7 +30,6 @@ import feign.InvocationHandlerFactory.MethodHandler;
import feign.Target;
import rx.Observable;
import rx.Single;
import rx.functions.Action1;
import static feign.Util.checkNotNull;
@ -38,11 +38,30 @@ final class HystrixInvocationHandler implements InvocationHandler { @@ -38,11 +38,30 @@ final class HystrixInvocationHandler implements InvocationHandler {
private final Target<?> target;
private final Map<Method, MethodHandler> dispatch;
private final Object fallback; // Nullable
private final Map<Method, Method> fallbackMethodMap;
HystrixInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch, Object fallback) {
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch");
this.fallback = fallback;
this.fallbackMethodMap = toFallbackMethod(dispatch);
}
/**
* If the method param of InvocationHandler.invoke is not accessible, i.e in a package-private
* interface, the fallback call in hystrix command will fail cause of access restrictions.
* But methods in dispatch are copied methods. So setting access to dispatch method doesn't take
* effect to the method in InvocationHandler.invoke. Use map to store a copy of method
* to invoke the fallback to bypass this and reducing the count of reflection calls.
* @return cached methods map for fallback invoking
*/
private Map<Method, Method> toFallbackMethod(Map<Method, MethodHandler> dispatch) {
Map<Method, Method> result = new HashMap<Method, Method>();
for (Method method : dispatch.keySet()) {
method.setAccessible(true);
result.put(method, method);
}
return result;
}
@Override
@ -72,7 +91,7 @@ final class HystrixInvocationHandler implements InvocationHandler { @@ -72,7 +91,7 @@ final class HystrixInvocationHandler implements InvocationHandler {
return super.getFallback();
}
try {
Object result = method.invoke(fallback, args);
Object result = fallbackMethodMap.get(method).invoke(fallback, args);
if (isReturnsHystrixCommand(method)) {
return ((HystrixCommand) result).execute();
} else if (isReturnsObservable(method)) {

Loading…
Cancel
Save