spring cloud openfeign 使用注意点

news2024/11/19 14:29:42

近期在做项目时给自己挖了一个坑,问题重现如下

使用的组件版本如下

spring boot 2.7.15,对应的 spring cloud 版本为 2021.0.5,其中 spring cloud 适配的 openfeign 版本是 3.1.5。

项目中使用的 feign 接口如下

public interface QueryApi {

    /**
     * 符合查询条件数据总数
     * @return
     */
    @PostMapping(value = "count")
    default CommonResponse count(
            @RequestParam(value = "indexName", required = true) @RequestParameterValue String indexName,
            @RequestParam(value = "queryFieldConditions", required = false) @Separator List<String> queryFieldConditions
    ) {
        return null;
    }
}

乍看没什么问题,只是加了一个 default 关键字,使用 java 8 的特性,java 的 interface 类型中的方法默认是 public abstract 的。

但是到了别的服务调用时就出现问题了,自己之前写的 feign 接口没问题,写法也类似,区别就是加了一个 default 关键字。

想不明白怎么就加了一个关键字就不行了,是哪里的逻辑判断的问题?

本着找问题到底的想法,在方法调用时跟进源码,发现在 ReflectiveFeign 中进了下图中的逻辑

进入 Util.isDefault() 中发现

通过与、或、且、相等四种运算判断了当前方法是否为 default。

写例子看一下加 default 和不加 default 的区别

不加 default 查看修饰符的和

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;


public class NoDefaultTest {

    public static void main(String[] args) {
        System.out.println("Modifier.SYNTHETIC " + 0x00001000);
        System.out.println("Modifier.ABSTRACT " + Modifier.ABSTRACT);
        System.out.println("Modifier.PUBLIC " + Modifier.PUBLIC);
        System.out.println("Modifier.STATIC " + Modifier.STATIC);

        int no = (Modifier.PUBLIC | Modifier.STATIC | Modifier.ABSTRACT | 0x00001000);
        System.out.println(no);

        int temp = 1 & no;
        System.out.println(temp);

        System.out.println("+++++++++++++++++++++++++++++++++++++++++++");

        Class<QueryApi> configurerClass = QueryApi.class;
        List<Method> methodList = Arrays.asList(configurerClass.getMethods());
        for (Method method : methodList) {
            System.out.println(method.getDeclaringClass().isInterface());
            System.out.println(method.getModifiers());
        }
    }
}

执行结果

Modifier.SYNTHETIC 4096
Modifier.ABSTRACT 1024
Modifier.PUBLIC 1
Modifier.STATIC 8
5129
1
+++++++++++++++++++++++++++++++++++++++++++
true
1025

可以发现,不加 default 的方法修饰符值为1025,即 public 和 abstract 的组合

加 default 查看修饰符的和

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;


public class DefaultTest {

    public static void main(String[] args) {
        System.out.println("Modifier.SYNTHETIC " + 0x00001000);
        System.out.println("Modifier.ABSTRACT " + Modifier.ABSTRACT);
        System.out.println("Modifier.PUBLIC " + Modifier.PUBLIC);
        System.out.println("Modifier.STATIC " + Modifier.STATIC);

        int no = (Modifier.PUBLIC | Modifier.STATIC | Modifier.ABSTRACT | 0x00001000);
        System.out.println(no);

        int temp = 1 & no;
        System.out.println(temp);

        System.out.println("+++++++++++++++++++++++++++++++++++++++++++");

        Class<QueryApi> configurerClass = QueryApi.class;
        List<Method> methodList = Arrays.asList(configurerClass.getMethods());
        for (Method method : methodList) {
            System.out.println(method.getDeclaringClass().isInterface());
            System.out.println(method.getModifiers());
        }
    }
}

执行结果

Modifier.SYNTHETIC 4096
Modifier.ABSTRACT 1024
Modifier.PUBLIC 1
Modifier.STATIC 8
5129
1
+++++++++++++++++++++++++++++++++++++++++++
true
1

可以发现,加 default 的方法修饰符值为1,即 public

以方法不加 default 修饰符来验证逻辑

判断代码为

((method.getModifiers()
        & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)) == Modifier.PUBLIC)
        && method.getDeclaringClass().isInterface()

下面拆开来验证

第一步

进行或运算使四个数相加

Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC

最终结果为 5129。接下来进行与运算

第二步

method.getModifiers()
        & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)

鉴于上面验证的不加 default 的方法修饰符值为1025,转二进制后为 1001

1 0100 0000 1001
            1001

两者计算结果为 1001,接下来与 Modifier.PUBLIC 进行等值比较

第三步

((method.getModifiers()
        & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)) == Modifier.PUBLIC)

由于 Modifier.PUBLIC 为1,所以两数不相等,后面还要跟当前方法所在类是否是接口进行且运算

第四步

method.getDeclaringClass().isInterface()

鉴于前面的判断为 false,后面为 true,所以结果为 false。

所以 Util.isDefault() 执行结果为 false,执行最后的 else 逻辑。

最终使用 jdk 的动态代理进行调用 MethodHandler 的实现类  SynchronousMethodHandler 来处理请求。

以方法加 default 修饰符来验证逻辑

从第二步来讲

 第二步

method.getModifiers()
        & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)

鉴于上面验证的加 default 的方法修饰符值为1,转二进制还是 1

1 0100 0000 1001
               1

两者计算结果为 1,接下来与 Modifier.PUBLIC 进行等值比较

第三步

((method.getModifiers()
        & (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)) == Modifier.PUBLIC)

由于 Modifier.PUBLIC 为1,所以两数相等,后面还要跟当前方法所在类是否是接口进行且运算

第四步

method.getDeclaringClass().isInterface()

鉴于前面的判断为 true,后面为 true,所以结果为 true。

最终调用 MethodHandler 的实现类 DefaultMethodHandler 来处理请求。

实际在调用 invoke() 的过程中没有执行结果,是 feign 针对 default 修饰的方法的一个 bug 还是我的调用方式有问题?

总结

定义的接口类中的方法中,修饰符是否添加有下面的情况

  1. 如果不声明修饰符,默认是 public abstract,对应的值为 1025。
  2. 如果声明修饰符 default,默认是 public,对应的值为 1。

为了防止 feign 调用出现一些其他未知的问题,还是不添加修饰符为好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1221671.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高性能音乐流媒体服务Diosic

什么是 Diosic ? Diosic 是一个开源的基于网络的音乐收集服务器和流媒体。主要适合需要部署在硬件规格不高的服务器上的用户。Diosic 是使用 Rust 开发的&#xff0c;具有低内存使用率和高性能以及用于流媒体音乐的非常干净的界面。 安装 在群晖上以 Docker 方式安装。 在注…

Jenkins自动化部署一个Maven项目

Jenkins自动化部署 提示&#xff1a;本教程基于CentOS Linux 7系统下进行 Jenkins的安装 1. 下载安装jdk11 官网下载地址&#xff1a;https://www.oracle.com/cn/java/technologies/javase/jdk11-archive-downloads.html 本文档教程选择的是jdk-11.0.20_linux-x64_bin.tar.g…

赋能汽车企业数智化转型,鼎捷软件受邀出席“中国工业软件大会”

由中国国际智能产业博览会组委会、工业和信息化部、重庆市人民政府主办的“第三届中国工业软件大会”在重庆盛大召开。工业软件主管部委及政府部门、产业上下游企业代表和业内大咖、科教领域专家学者等800余位嘉宾代表齐聚&#xff0c;为加快制造业数字化转型和高质量发展建言献…

基于SpringBoot的SSMP整合案例(在Linux中发布项目的注意事项与具体步骤步骤)

前言与注意 这几天在Linux中上线之前的小项目时&#xff0c;遇到了很多的问题&#xff0c;Linux镜像的选择&#xff0c;jdk&#xff0c; mysql在linux中的下载&#xff0c;使用finallshell连接linux&#xff0c;使用tomcat连接linux中的数据库........ 在下面的注意事项中我会将…

人生阶段总结

--回顾一下我迷茫、努力、不开心又失败的阶段人生自我介绍一下&#xff0c;我是一个智力平平&#xff0c;记忆力差&#xff0c;适合自学的长睡眠者。 大专之前 国内的应试教育基本上不适合我&#xff0c;厌恶补课厌恶机械式听课刷题&#xff0c;所有的优势学科都是自学&#xf…

Sql Server 2017主从配置之:事务日志传送

使用事务日志传送模式搭建Sql Server 2017主从同步&#xff0c;该模式有一定的延迟&#xff0c;是通过3个不同的定时任务&#xff0c;将主库的日志同步到从库进行恢复来实现数据库同步操作。 环境准备 两台服务器&#xff0c;配置都是8g2核&#xff0c;50g硬盘&#xff0c;操…

CI/CD相关概念学习

文章目录 CI/CD相关概念学习前言CI/CD相关概念介绍集成地狱持续集成持续交付持续部署Devops CI/CD相关应用介绍JenkinsTekton PipelinesSpinnakerTravis CIGoCD CI/CD相关概念学习 前言 本文主要是介绍一些 CI/CD 相关的概念&#xff0c;通过阅读本文你将快速了解 CI/CD 是什么…

腾讯云4核8G服务器性能如何多少钱一年?

腾讯云服务器4核8G配置优惠价格表&#xff0c;轻量应用服务器和CVM云服务器均有活动&#xff0c;云服务器CVM标准型S5实例4核8G配置价格15个月1437.3元&#xff0c;5年6490.44元&#xff0c;轻量应用服务器4核8G12M带宽一年446元、529元15个月&#xff0c;腾讯云百科txybk.com分…

在前端开发中,什么是CDN(Content Delivery Network)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

Python实验项目7 :tkinter GUI编程

&#xff08;1&#xff09;利用tkinter 制作界面&#xff0c;效果图如下&#xff1a; from tkinter import * # winTk() for i in range(1,20):Button(width5,height10,bg"black" if i%20 else"white").pack(side"left") win.geometry("8…

“可信区块链运行监测服务平台TBM发展研讨会”将于11月23日在北京召开

为推动区块链治理与创新&#xff0c;积极推进信任科技生态体系建设&#xff0c;中国信息通信研究院、中国移动设计院联合区块链服务网络&#xff08;BSN&#xff09;发展联盟共同发起建立了可信区块链运行监测服务平台&#xff08;TBM&#xff09;。 TBM平台通过对区块链系统的…

idea显示pom.xml文件漂黄警告 Dependency maven:xxx:xxx is vulnerable

场景&#xff1a; idea警告某些maven依赖包有漏洞或者依赖传递有易受攻击包&#xff0c;如下&#xff1a; 解决&#xff1a; 1、打开idea设置&#xff0c;找到 File | Settings | Editor | Inspections 2、取消上述两项勾选即可

Verilog基础:仿真时x信号的产生和x信号对于各运算符的特性

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 信号爆x也许是所有IC人的噩梦&#xff0c;满屏的红色波形常让人头疼不已&#xff0c;但x信号的产生原因却常常只有几种&#xff0c;只要遵循一定的代码规范&#…

开源与闭源软件的辩论:对大模型技术发展的影响

目录 前言1 开源软件的优缺点1.1 开源软件的优点1.2 开源软件的缺点和挑战 2 闭源软件的优缺点2.1 闭源软件的优点2.2 闭源软件的缺点和挑战 3 大模型发展会走向哪一边结语 前言 近期&#xff0c;特斯拉CEO马斯克公开表示&#xff1a;OpenAI不该闭源&#xff0c;自家首款聊天机…

JVM判断对象是否存活之引用计数法、可达性分析

目录 前言 引用计数法 概念 优点 缺点 可达性分析 概念 缺点&#xff1a; 扩展&#xff1a; 1.GC Roots 概念 2.STW (Stop the world) 前言 JVM有两种算法来判断对象是否存活&#xff0c;分别是引用计数法和可达性分析算法&#xff0c;针对可达性分析算法STW时间长、…

Python入门学习篇(一)——注释变量输入输出

1 注释 1.1 作用 a 方便他人和自己阅读代码 b 告诉编译器这部分内容是不用执行的。1.2 单行注释 # 注释内容1.3 多行注释(引号) 1.3.1 三对双引号 """ 注释内容 """1.3.2 三对单引号 注释内容 1.4 pycharm快捷键使用 ctrl/ 多行注释(以# …

基于SSM的中小型企业财务管理设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【413.等差数列划分】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:int numberOfArithmeticSlices(vector<int>& nums) {int nnums.size();if(n<3) return 0;vector<int> dp(n);dp[2]dp[1]dp[0]0;if(nums[2]-nu…

vulnhub靶场—matrix-breakout-2-morpheus靶机

一&#xff0c;实验环境 靶机ip&#xff1a;192.168.150.131攻击机ip&#xff1a;192.168.150.130 二&#xff0c;信息收集 arp-scan -l 扫描网段&#xff0c;寻找靶机ip 使用工具nmap进行端口扫描 nmap -A -T4 -p- 192.168.150.131 通过信息收集发现了靶机有80和81这两个…

【2021集创赛】基于arm Cortex-M3处理器与深度学习加速器的实时人脸口罩检测 SoC

团队介绍 参赛单位&#xff1a;深圳大学 队伍名称&#xff1a;光之巨人队 指导老师&#xff1a;钟世达、袁涛 参赛队员&#xff1a;冯昊港、潘家豪、慕镐泽 图1 团队风采 1. 项目简介 新冠疫情席卷全球&#xff0c;有效佩戴口罩可以极大程度地减小病毒感染的风险。本项目开发…