spring-cloud-feign因为日志等级调整引起的bug,日志等级设置为debug正常,设置为info则不正常,撸源码查找解决问题

背景

  1. 之前项目使用springboot,接口参数和返回值都使用下划线,项目中实体类都使用的驼峰,所以设置了jackson的统一配置(spring.jackson.property-naming-strategy=SNAKE_CASE),把下划线转换成了驼峰。
  2. 项目开始使用spring-cloud-feign,对接其它项目,其它项目中的参数和返回值有的使用驼峰,有的使用下划线,所以上述1中的配置不能使用
  3. 查看@FeignClient的配置可以设置 encoder和decoder,org.springframework.cloud.openfeign.FeignClient#configuration

因此对FeignClient设置了encoder和decoder,
在这里插入图片描述

可是日志配置文件中logback.level=debug的时候接口都正常,logback.level=info的时候接口不能正常解析
所以,为了搞清问题出在什么地方,打算撸一遍源码看看什么问题

解决方案

先上解决方案 代码

IOC中FeignClient注册流程:

  1. 第一步因为需要@EnableFeignClients打开FeignClient的注册,所以查看@EnableFeignClients的源码,发现会import FeignClientsRegistrar类,所以查看FeignClientsRegistrar类
    在这里插入图片描述

  2. 第二步 查看FeignClient的注册流程,在.FeignClientsRegistrar 类中可以看到IOC注册的是FeignClientFactoryBean
    在这里插入图片描述

  3. 查看FeignClientFactoryBean类,FeignClientFactoryBean实现了FactoryBean接口,因此在IOC容器中 get FeignClient的时候,会调用org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject 方法实例化当前对象,getObject()最终调用org.springframework.cloud.openfeign.Targeter#target 生成返回值
    在这里插入图片描述

  4. 查看org.springframework.cloud.openfeign.Targeter 类,发现是一个接口,查看他的实现类,发现有2个,具体用的哪个呢?.在这里插入图片描述

  5. 查看FeignAutoConfiguration源码,发现如果配置了断路器,用的就是HystrixTargeter,否则就是DefaultTargeter,我们用的是DefaultTargeter
    在这里插入图片描述

  6. 进入DefaultTargeter,发现调用了Feign.Builder的target方法在这里插入图片描述

  7. 进入Feign.Builder,发现调用了feign.Feign.Builder#build 创建ReflectiveFeign对象,再调用feign.ReflectiveFeign#newInstance,终于到了实例列feign对象在这里插入图片描述

  8. 进入ReflectiveFeign ,查看feign.ReflectiveFeign#newInstance方法,我们feign.ReflectiveFeign#newInstance在发现了生成代理类,进入生成代理类的方法中
    在这里插入图片描述

  9. 查看生成的代理类,发现最后返回的是feign.ReflectiveFeign.FeignInvocationHandler,我们知道最终执行的都是代理类中的方法,即java.lang.reflect.InvocationHandler#invoke方法

在这里插入图片描述

  1. 查看代理类的invoke方法,发现是从dispatch中获取方法并执行

在这里插入图片描述

  1. 查看dispatch中获取到的value,发现是feign.SynchronousMethodHandler,现在知道最终执行的是feign.SynchronousMethodHandler#invoke方法

在这里插入图片描述

  1. 还记得刚开始的问题(log.level=debug时,接口正常;log.level=info时接口不正常)吗,知道了最终执行的feign.SynchronousMethodHandler#invoke方法 ,所以在该方法中查找跟log.level相关的代码,打个断点追踪一下,查看调用链路,发现:

判断如果log.level=debug的话,把返回结果拿到,打印日志,然后封装body变成了ByteArrayBody
如果log.level !=debug ,则把原Respone返回,Respone中的body是 InputStream
综合以上两点,得出结论,如果想要自己写@FeignClient中的Decoder,那么需要处理结果从ByteArrayBody获取,和InputStream中获取
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

走着路睡觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值