zoukankan      html  css  js  c++  java
  • 记遇见的一次AbstractMethodError

    问题:

    • Spring Cloud Version:Hoxton.SR3
    • Spring Cloud Alibaba Version:2.2.0.RELEASE

    项目中consumer端使用@FeignClient定义接口,启动报错:

    Caused by: java.lang.AbstractMethodError: com.alibaba.cloud.sentinel.feign.SentinelContractHolder.parseAndValidateMetadata(Ljava/lang/Class;)Ljava/util/List;
    	at feign.ReflectiveFeign$ParseHandlersByName.apply(ReflectiveFeign.java:151) ~[feign-core-10.7.4.jar:na]
    	at feign.ReflectiveFeign.newInstance(ReflectiveFeign.java:49) ~[feign-core-10.7.4.jar:na]
    

    分析:

    Spring Cloud从Hoxton.SR1版本开始,依赖的spring-cloud-starter-openfeign版本为2.2.2.RELEASE;
    Spring Cloud Alibaba 2.2.0.RELEASE依赖的spring-cloud-openfeign-dependencies版本为2.2.0.RELEASE;

    feign的Contract接口,
    2.2.0.RELEASE:

    // TODO: break this and correct spelling at some point
    List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType);
    

    2.2.2.RELEASE:

    List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType);
    

    在2.2.0.RELEASE里有一行注释描述,接口方法名拼写错误,在2.2.2.RELEASE方法已修正了,即方法名发生了改变。

    spring-cloud-alibaba-sentinel中的SentinelContractHolder类,用到了该接口的这个方法(feign2.2.0.RELEASE版本):

    @Override
    public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) {
    	List<MethodMetadata> metadatas = delegate.parseAndValidatateMetadata(targetType);
    	metadatas.forEach(metadata -> METADATA_MAP
    			.put(targetType.getName() + metadata.configKey(), metadata));
    	return metadatas;
    }
    

    解决:

    以下3中方式均可:

    • 修改Spring Cloud版本,Hoxton.SR3改为Hoxton.RELEASE

    • 在dependencyManagement中指定spring-cloud-openfeign-dependencies的版本为2.2.0.RELEASE

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-openfeign-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    

    注意spring-cloud-openfeign-dependencies写在spring-cloud-dependencies前面,因为dependency前面的优先生效。

    • 在项目中相同包路径下新建SentinelContractHolder类,方法实现和spring-cloud-alibaba-sentinel相同,修改Contract接口为新版版本的方法名即可。

    总结:

    1. AbstractMethodError是ERROR的子类,不能在编译时检查出来,运行时才会触发

    2. A依赖于B,运行时JVM发现B的class文件和编译时不一致会抛该异常,一般是因为B有多个版本,版本不兼容导致,比如方法签名变了。

  • 相关阅读:
    简述对vuex的理解
    Vuex总结--是什么?有什么?怎么用?
    Vuex总结
    在vue中,methods和computed这两个方法的区别。
    关于vuex
    生命周期的钩子函数
    vuex 的理解
    Linux 安装kubectl
    python装饰器
    MySQL事务
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/12537412.html
Copyright © 2011-2022 走看看