Koltin + SpringBoot MVC接口映射重复异常

在更新了Kotlin1.3之后,项目的启动抛出了如下异常

java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'xxxx' method 

抛出异常方法是一个有默认参数的方法,那么在字节码反映出的,是会生成对应的重载方法(用Java的视角看)
异常产生原因是因为在Kotlin1.3编译出的字节码中,这个生成的重载方法相对Kotlin1.3相较之前少了一个方法标识 ACC_BRIDGE,即生成的方法不再是桥接方法

// 使用javap -verbose 查看class文件
// Kotlin1.3 
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNTHETIC

// Kotlin1.2
flags: ACC_PUBLIC, ACC_STATIC, ACC_BRIDGE, ACC_SYNTHETIC

在SpringMVC启动前,进行方法和RequestMapping的映射注册,对@Controller类下的Mapping方法进行扫描并找出真实的Method对象,其核心方法如下:

// BridgeMethodResolver类方法
public static Method findBridgedMethod(Method bridgeMethod) {
        if (bridgeMethod != null && bridgeMethod.isBridge()) {
            List<Method> candidateMethods = new ArrayList();
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(bridgeMethod.getDeclaringClass());
            Method[] var3 = methods;
            int var4 = methods.length;

            for(int var5 = 0; var5 < var4; ++var5) {
                Method candidateMethod = var3[var5];
                if (isBridgedCandidateFor(candidateMethod, bridgeMethod)) {
                    candidateMethods.add(candidateMethod);
                }
            }

            if (candidateMethods.size() == 1) {
                return (Method)candidateMethods.get(0);
            } else {
                Method bridgedMethod = searchCandidates(candidateMethods, bridgeMethod);
                if (bridgedMethod != null) {
                    return bridgedMethod;
                } else {
                    return bridgeMethod;
                }
            }
        } else {
            return bridgeMethod;
        }
    }

因为没有了ACC_BRIDGE标志(isBridge()会返回false),所以默认参数对应的 Method 会进入到 if 分支,对于进入该分支的 Method 对象,经过检查后会假如备选列表中并等待返回

private static boolean isBridgedCandidateFor(Method candidateMethod, Method bridgeMethod) {
        return !candidateMethod.isBridge() && !candidateMethod.equals(bridgeMethod) && candidateMethod.getName().equals(bridgeMethod.getName()) && candidateMethod.getParameterTypes().length == bridgeMethod.getParameterTypes().length;
    }

显然,方法会通过检查并最终完成注册,这就导致同一个RequestMapping下注册了两个方法,导致应用的启动异常

解决方案(选其一):

  • Kotlin编译等级降到1.2
  • SpringBoot版本升级到2.x.x以上
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值