Feign源码剖析之请求头丢失
2022-03-27 16:26:11 0 举报
对于Feign想深入研究的开发者,有恨到的帮助
作者其他创作
大纲/内容
target包含信息:name = \"service-list\"type = {Class@7354} \"interface com.atguigu.gmall.feign.list.GoodsFeignClient\"url = \"http://service-list\"
获取serviceName=service-list
根据服务名,从Spring容器中找到Client类型的Bean
applicationContext.getBean(FeignContext.class)
invoke
Feign.Builder builder = feign(context)
this.targetRequest(template)
拿到扫描器
这里使用了Spring的扫描机制来完成.
RequestTemplate template = new RequestTemplate(老请求中除开请求头和queries这两个之外的所有信息)
new RibbonRequest(参数信息)
所有带@FeignClient注解的interface都被封装成FeignClientFactoryBean的BeanDefinition
判断当前执行的方法是不是equals、hashcode、或者toString
this.buildTemplateFromArgs.create()
得到HystrixTargeter
RequestTemplate.from(this.metadata.template())
将条件过滤器对象添加到扫描器Scanner中
1
创建一个RequestTemplate对象,取出老请求中的所有信息【除开 queries、heads】,给封装到新的请求中去
用RibbonRequest对象封装远程调用的参数信息
调用HystrixTargeter.target()方法
2
Spring容器启动的时候
执行内部类中的invoke
scanner.findCandidateComponents(basePackage)
url += cleanPath();
FeignInvocationHandler
使用JDk动态代理生成代理对象,那么代理逻辑即为handler实现类中的invoke()方法
返回创建的新请求Return template
获取uriWithoutHost=http:///api/inner/search/goods
getObject()
BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class)
this.executeAndDecode
mutable.feignTarget(this.target)
LoadBalancerFeignClient
得到对象类型SynchronousMethodHandler
拼接url
Factory接口只有一个实现类ReflectiveFeign
ReflcetiveFeign属性初始化完毕
执行RequestTemplate类中的Factory接口里的create方法
将target设置到新请求中
从bulid对象中取出参数,封装到synchronousMethodHandlerFactory中,进行构建ReflectiveFeign对象,完成ReflcetiveFeign属性的初始化
实际调用create的对象是InvocationHandlerFactory的create
registerBeanDefinitions
ReflectiveFeign
(MethodHandler)this.dispatch.get(method)
excute()
implements ImportBeanDefinitionRegistrar
获取到每一个组件上的FeignClient注解属性
开始注册
basePackages = getBasePackages(metadata)
FeignAutoConfiguration
返回代理对象
getTarget()
调用Feign方法,获取构建器
判断不是HystrixFeign.Builder
Feign的核心入口方法
使用Sping的import技术
TraceLoadBalancerFeignClient
有一个内部类 并且实现了InvocationHandle
metadata.getAnnotationAttributes(EnableFeignClients.class.getName())
EnableFeignClients
拿到目标对象中所有方法,进行遍历
拿到扫描包路径
newInstance(target)
super.excute
annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName())
factory.create【得到的是一个InvocationHandler】
重写
参数构建完毕
Feign注册流程完毕
getClientName(attributes)
FeignContext处理了我们自定义的@FeignClient以及全局@EnableFeignClients中配置的日志,加、解密器,验证器等,最后configureFeign,处理了链接超时、读取超时等配置项,初次之外还有一个很重要的信息拦截器
scanner.addIncludeFilter(annotationTypeFilter)
this.metadata.template()得到一个RequestTemplate在哪里初始化的???
获取Feign内部类Bulid对象
得到LoadBalancerFeignClient
FeignClientFactoryBean.class
build().newInstance(target)
遍历扫描到的候选Components
获取asuri=http://service-list/api/inner/search/goods
拿到EnableFeignClient注解上的属性
从Spring容器根据类型中获取FeignContext对象,那么在哪里完成实例化以及初始化的?
若不是,执行
远程调用之前先进入到invoke()
FeignClientsRegistrar.class
完成代理对象的生成
bulid方法
像Spring容器中注册FeignClient
判断请求请求头以及queries是否为空,不为空,则add到新请求中去,
feign.target(target)
这个配置类中没有做其它的事情,其中有一件事就是定义FeignContext这个bean 并放到Spring容器的单例池中
最终注册到Spring容器的bdmap中,让开发人员可以@Autowired来调用
去创建一个RequestTemplate对象
拿到注解属性中的服务名字
因为这个Map中封装了当前方法以及同步器,【代理逻辑主要就在这个同步器对象里完成】那么什么时候去操作这个Map?
至此,Spring启动阶段,各个事件都处理完毕
new AnnotationTypeFilter(FeignClient.class)
用FeignLoadBalancer对象真正完成远程调用
进入到Feign类中,调用其build方法
初始化Feign内部类Builder中各个属性
返回新请求Return template
getScanner()
创建一个新的Balance
扫描指定包下加了@Component注解的类
ReflectiveFeign.create()
0 条评论
回复 删除
下一页