交流
商城
MCN
登入
注册
首页
提问
分享
讨论
建议
公告
动态
发表新帖
发表新帖
Fegin 第3 章:FeignInvocationHandler
分享
未结
0
1120
李延
LV6
2021-06-21
悬赏:20积分
# 作用 在前面分析中,我们知道fegin最后使用的jdk代理。而FeignInvocationHandler就是这个代理类 # invoke 我们知道jdk代理继承子InvocationHandler当我们调用被代理对象的方法时,使用的就是invoke方法。我们看一下这个方法 ```java @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("equals".equals(method.getName())) { try { Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null; return equals(otherHandler); } catch (IllegalArgumentException e) { return false; } } else if ("hashCode".equals(method.getName())) { return hashCode(); } else if ("toString".equals(method.getName())) { return toString(); } return dispatch.get(method).invoke(args); } ``` 这里我们看到首先是对object类一些方法特殊处理,这里我们先暂时不解析,主要看我们自己定义的方法 ```java return dispatch.get(method).invoke(args); ``` 这里我们看到这里是通过dispatch对象实现的。我们在其构造方法中看到了这个方法 ```java private final Map<Method, MethodHandler> dispatch; FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) { this.target = checkNotNull(target, "target"); this.dispatch = checkNotNull(dispatch, "dispatch for %s", target); } ``` 也就是说通过构造方法传入一个map这个map,key是Method对象,value是MethodHandler对象。通过判断调用的方法获取到对应的MethodHandler,而方法具体执行的逻辑是再MethodHandler中。 我们回头再看一下这个 Map<Method, MethodHandler> dispatch是在哪里生成的。 # dispatch初始化 在 ReflectiveFeign类的newInstance方法中我们看到: ```java public <T> T newInstance(Target<T> target) { Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target); Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>(); List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>(); //遍历当前接口的定义的每个方法 for (Method method : target.type().getMethods()) { //Object下的方法 if (method.getDeclaringClass() == Object.class) { continue; // 有默认实现的方法 } else if (Util.isDefault(method)) { DefaultMethodHandler handler = new DefaultMethodHandler(method); defaultMethodHandlers.add(handler); methodToHandler.put(method, handler); //接口 } else { methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method))); } } InvocationHandler handler = factory.create(target, methodToHandler); T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[] {target.type()}, handler); for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) { defaultMethodHandler.bindTo(proxy); } return proxy; } ``` 在这里我们看到这个map的创建过程,我们主要关注的是接口方法。我们发现它是通过nameToHandler生成的。 通过debug我们看一下nameToHandler对象  也就是说它的key是string 跟进类名+方法名+参数名 等一系列参数,而MethodHandler对象在此时已经创建。 在方法第一行我们看到 ```java Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target); ``` nameToHandler是通过targetToHandlersByName生成。 我们继续返回Fegin类看一下targetToHandlersByName创建过程 ```java SynchronousMethodHandler.Factory synchronousMethodHandlerFactory = new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger, logLevel, decode404, closeAfterDecode, propagationPolicy, forceDecoding); ParseHandlersByName handlersByName = new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder, errorDecoder, synchronousMethodHandlerFactory); return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder); ``` # 总结 我们跟踪FeignInvocationHandler代码发现fegin的处理逻辑是通过MethodHandler对象来实现的,而MethodHandler对象的生成又是通过ParseHandlersByName来创建的。 所有我们下面的内容主要关注点就是ParseHandlersByName是如何创建出MethodHandler的,而MethodHandler有是如何发送请求的。
回帖
消灭零回复
提交回复
热议榜
java 相关知识分享
8
好的程序员与不好的程序员
6
写给工程师的十条精进原则
5
spring boot以jar包运行配置的logback日志文件没生成
5
一步一步分析SpringBoot启动源码(一)
5
MockMvc测试
5
【吐槽向】是不是有个吐槽的板块比较好玩
4
logstash jdbc同步mysql多表数据到elasticsearch
3
IntelliJ IDEA 优质License Server
3
.gitignore忽略规则
3
SpringBoot启动源码分析
3
一步一步分析SpringBoot启动源码(三)
3
2
一步一步分析SpringBoot启动源码(二)
2
积分不够将无法发表新帖
2
官方产品
Meta-Boot - 基于MCN
MCN - 快速构建SpringBoot应用
微信扫码关注公众号