OpenFeign的调用源码解析InvocationHandlerFactory 和MethodHandler类
步骤 1: Java 动态代理基础回顾
Java 动态代理通过 java.lang.reflect.Proxy
类创建代理对象,核心是 InvocationHandler
接口。当调用代理对象的方法时,会触发 InvocationHandler.invoke()
方法,该方法负责处理实际逻辑:
- 用途:实现 AOP(面向切面编程)、远程调用等。
- 标准实现:
例如,创建代理:public interface InvocationHandler { Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
但在框架中,InvocationHandler handler = (proxy, method, args) -> { // 处理逻辑 return null; }; MyInterface proxy = (MyInterface) Proxy.newProxyInstance( MyInterface.class.getClassLoader(), new Class<?>[]{MyInterface.class}, handler );
InvocationHandler
的创建和逻辑可能更复杂,需要解耦——这就引入了InvocationHandlerFactory
和MethodHandler
。
步骤 2: InvocationHandlerFactory 的用途与实现
InvocationHandlerFactory
是 Feign 框架中的接口,用于创建 InvocationHandler
实例。其核心目的是解耦 InvocationHandler 的创建过程,便于扩展(如支持 Hystrix 熔断)。
-
用途:
- 根据方法处理程序(
MethodHandler
)动态生成InvocationHandler
实现类(如FeignInvocationHandler
)。 - 在 Feign 中,它确保每个代理接口的方法调用最终映射到 HTTP 请求。
- 根据方法处理程序(
-
实现细节(基于 Feign 源码):
- 接口定义(简化):
public interface InvocationHandlerFactory { InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch); }
- 默认实现类
Default
:在 Feign 的ReflectiveFeign
类中,DefaultInvocationHandlerFactory
根据MethodHandler
映射创建FeignInvocationHandler
。- 关键逻辑:为每个接口方法绑定一个
MethodHandler
,FeignInvocationHandler
在invoke()
方法中根据调用的方法查找对应的MethodHandler
并执行。 - 源码示例(伪代码):
在 Feign 初始化时,// FeignInvocationHandler 实现 class FeignInvocationHandler implements InvocationHandler { private final Map<Method, MethodHandler> dispatch; public Object invoke(Object proxy, Method method, Object[] args) { // 从 dispatch 映射获取 MethodHandler 并调用 return dispatch.get(method).invoke(args); } } // DefaultInvocationHandlerFactory 创建 InvocationHandler public class DefaultInvocationHandlerFactory implements InvocationHandlerFactory { @Override public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) { return new FeignInvocationHandler(target, dispatch); // 创建 FeignInvocationHandler } }
ReflectiveFeign.newInstance()
方法使用DefaultInvocationHandlerFactory
生成代理对象。
- 关键逻辑:为每个接口方法绑定一个
- 接口定义(简化):
步骤 3: MethodHandler 的用途与实现
MethodHandler
是 Feign 框架中的另一个接口,用于封装单个方法的调用逻辑(如构建 HTTP 请求、解析响应)。每个接口方法都有一个对应的 MethodHandler
实例。
-
用途:
- 将 Java 方法调用转换为 HTTP 操作(GET/POST 等)。
- 处理注解(如
@RequestLine
),生成请求参数、头信息等。
-
实现细节(基于 Feign 源码):
- 接口定义(简化):
public interface MethodHandler { Object invoke(Object[] args) throws Throwable; }
- 默认实现类
SynchronousMethodHandler
:这是 Feign 中最常用的实现,负责同步 HTTP 调用。- 关键逻辑:在
invoke()
方法中,使用RequestTemplate
构建 HTTP 请求,通过客户端(如OkHttpClient
)发送请求并解析响应。 - 源码示例(伪代码):
class SynchronousMethodHandler implements MethodHandler { private final MethodMetadata metadata; // 方法元数据(注解解析结果) private final Target target; // 目标 URL private final Client client; // HTTP 客户端 @Override public Object invoke(Object[] args) { // 1. 构建请求模板 RequestTemplate template = buildTemplateFromArgs(args); // 2. 发送 HTTP 请求 Response response = client.execute(template.request(), options); // 3. 解码响应 return decoder.decode(response, metadata.returnType()); } }
- 关键逻辑:在
- 创建过程:在 Feign 的
Contract
组件解析方法注解后,ReflectiveFeign
会为每个方法生成一个MethodHandler
,并存储在映射中供InvocationHandlerFactory
使用。
- 接口定义(简化):
步骤 4: 整体协作关系总结
在 Spring Cloud Feign 中,InvocationHandlerFactory
和 MethodHandler
协作实现动态代理:
- 初始化阶段:
Contract
解析@FeignClient
接口的方法注解。- 为每个方法创建
MethodHandler
(如SynchronousMethodHandler
)。 InvocationHandlerFactory
(默认Default
实现)使用这些MethodHandler
创建FeignInvocationHandler
。
- 调用阶段:
- 用户调用代理方法 →
FeignInvocationHandler.invoke()
触发 → 查找对应MethodHandler
→MethodHandler.invoke()
执行 HTTP 调用。 - 例如:
userService.getUser(id)
会转换为GET /user/{id}
请求。
- 用户调用代理方法 →
优势:
- 解耦:
InvocationHandlerFactory
允许自定义InvocationHandler
(如HystrixInvocationHandler
支持熔断)。 - 高效:
MethodHandler
预编译方法逻辑,减少运行时开销。 - 扩展性:通过实现这些接口,可以添加日志、重试等切面功能。