Skip to content

Commit 2ef3bc8

Browse files
liuzhengyangAdrian Cole
authored andcommitted
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 OpenFeign#353
1 parent 64184e9 commit 2ef3bc8

1 file changed

Lines changed: 21 additions & 2 deletions

File tree

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
import java.lang.reflect.InvocationHandler;
2323
import java.lang.reflect.InvocationTargetException;
2424
import java.lang.reflect.Method;
25+
import java.util.HashMap;
2526
import java.util.Map;
2627

2728
import feign.InvocationHandlerFactory;
2829
import feign.InvocationHandlerFactory.MethodHandler;
2930
import feign.Target;
3031
import rx.Observable;
3132
import rx.Single;
32-
import rx.functions.Action1;
3333

3434
import static feign.Util.checkNotNull;
3535

@@ -38,11 +38,30 @@ final class HystrixInvocationHandler implements InvocationHandler {
3838
private final Target<?> target;
3939
private final Map<Method, MethodHandler> dispatch;
4040
private final Object fallback; // Nullable
41+
private final Map<Method, Method> fallbackMethodMap;
4142

4243
HystrixInvocationHandler(Target<?> target, Map<Method, MethodHandler> dispatch, Object fallback) {
4344
this.target = checkNotNull(target, "target");
4445
this.dispatch = checkNotNull(dispatch, "dispatch");
4546
this.fallback = fallback;
47+
this.fallbackMethodMap = toFallbackMethod(dispatch);
48+
}
49+
50+
/**
51+
* If the method param of InvocationHandler.invoke is not accessible, i.e in a package-private
52+
* interface, the fallback call in hystrix command will fail cause of access restrictions.
53+
* But methods in dispatch are copied methods. So setting access to dispatch method doesn't take
54+
* effect to the method in InvocationHandler.invoke. Use map to store a copy of method
55+
* to invoke the fallback to bypass this and reducing the count of reflection calls.
56+
* @return cached methods map for fallback invoking
57+
*/
58+
private Map<Method, Method> toFallbackMethod(Map<Method, MethodHandler> dispatch) {
59+
Map<Method, Method> result = new HashMap<Method, Method>();
60+
for (Method method : dispatch.keySet()) {
61+
method.setAccessible(true);
62+
result.put(method, method);
63+
}
64+
return result;
4665
}
4766

4867
@Override
@@ -72,7 +91,7 @@ protected Object getFallback() {
7291
return super.getFallback();
7392
}
7493
try {
75-
Object result = method.invoke(fallback, args);
94+
Object result = fallbackMethodMap.get(method).invoke(fallback, args);
7695
if (isReturnsHystrixCommand(method)) {
7796
return ((HystrixCommand) result).execute();
7897
} else if (isReturnsObservable(method)) {

0 commit comments

Comments
 (0)