Spring Cloud Feign实战来袭:工程中配置断路器Hystrix报错NoClassDefFoundError:HystrixCommandAspect解决方案

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。Spring Cloud Feign实战来袭:工程中配置断路器Hystrix报错NoClassDefFoundError:HystrixCommandAspect解决方案,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1、Spring Cloud Feign工程中配置断路器Hystrix

在这里插入图片描述

在Spring Cloud Feign工程中配置断路器Hystrix的时候,pom.xml文件已经加入Hystrix相关的jar:

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
		</dependency>

Application.java:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
@EnableHystrixDashboard
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

2、当启动的时候,报如下错误 NoClassDefFoundError:


Exception in thread "main" java.lang.NoClassDefFoundError: com/netflix/hystrix/contrib/javanica/aop/aspectj/HystrixCommandAspect
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
	at java.lang.Class.getDeclaredMethods(Class.java:1975)
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:613)
	at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:524)
	at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:510)
	at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:570)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:697)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:640)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609)
	at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1484)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:515)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:508)
	at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:1186)
	at org.springframework.boot.SpringApplication.getExitCodeFromMappedException(SpringApplication.java:818)
	at org.springframework.boot.SpringApplication.getExitCodeFromException(SpringApplication.java:804)
	at org.springframework.boot.SpringApplication.handleExitCode(SpringApplication.java:790)
	at org.springframework.boot.SpringApplication.handleRunFailure(SpringApplication.java:744)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1118)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1107)

可以看出来是找不到HystrixCommandAspec.java这个类,于是在github上找到这个源文件:

3、查看源码(切记:一定要学会查看源码)

https://github.com/dmgcodevil/Hystrix/blob/958ec5d7b4bb967be077a4c2bbcdc71e7a7f5248/hystrix-contrib/hystrix-javanica/src/main/java/com/netflix/hystrix/contrib/javanica/aop/aspectj/HystrixCommandAspect.java

在这里插入图片描述
源码如下:

/**
 * Copyright 2012 Netflix, Inc.
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.netflix.hystrix.contrib.javanica.aop.aspectj;

import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.netflix.hystrix.HystrixExecutable;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.collapser.CommandCollapser;
import com.netflix.hystrix.contrib.javanica.command.CommandExecutor;
import com.netflix.hystrix.contrib.javanica.command.ExecutionType;
import com.netflix.hystrix.contrib.javanica.command.GenericHystrixCommandFactory;
import com.netflix.hystrix.contrib.javanica.command.MetaHolder;
import com.netflix.hystrix.exception.HystrixBadRequestException;
import org.apache.commons.lang3.Validate;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;


import static com.netflix.hystrix.contrib.javanica.utils.AopUtils.getDeclaredMethod;
import static com.netflix.hystrix.contrib.javanica.utils.AopUtils.getMethodFromTarget;
import static com.netflix.hystrix.contrib.javanica.utils.EnvUtils.isCompileWeaving;
import static com.netflix.hystrix.contrib.javanica.utils.ajc.AjcUtils.getAjcMethodAroundAdvice;

/**
 * AspectJ aspect to process methods which annotated with {@link HystrixCommand} annotation.
 */
@Aspect
public class HystrixCommandAspect {

    private static final Map<HystrixPointcutType, MetaHolderFactory> META_HOLDER_FACTORY_MAP;

    static {
        META_HOLDER_FACTORY_MAP = ImmutableMap.<HystrixPointcutType, MetaHolderFactory>builder()
                .put(HystrixPointcutType.COMMAND, new CommandMetaHolderFactory())
                .put(HystrixPointcutType.COLLAPSER, new CollapserMetaHolderFactory())
                .build();
    }

    @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")

    public void hystrixCommandAnnotationPointcut() {
    }

    @Pointcut("@annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser)")
    public void hystrixCollapserAnnotationPointcut() {
    }

    @Around("hystrixCommandAnnotationPointcut() || hystrixCollapserAnnotationPointcut()")
    public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
        Method method = getMethodFromTarget(joinPoint);
        Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint);
        if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) {
            throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " +
                    "annotations at the same time");
        }
        MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method));
        MetaHolder metaHolder = metaHolderFactory.create(joinPoint);
        HystrixExecutable executable;
        ExecutionType executionType = metaHolder.isCollapser() ?
                metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType();
        if (metaHolder.isCollapser()) {
            executable = new CommandCollapser(metaHolder);
        } else {
            executable = GenericHystrixCommandFactory.getInstance().create(metaHolder, null);
        }
        Object result;
        try {
            result = CommandExecutor.execute(executable, executionType);
        } catch (HystrixBadRequestException e) {
            throw e.getCause();
        }
        return result;
    }

    /**
     * A factory to create MetaHolder depending on {@link HystrixPointcutType}.
     */
    private static abstract class MetaHolderFactory {
        public MetaHolder create(final ProceedingJoinPoint joinPoint) {
            Method method = getMethodFromTarget(joinPoint);
            Object obj = joinPoint.getTarget();
            Object[] args = joinPoint.getArgs();
            Object proxy = joinPoint.getThis();
            return create(proxy, method, obj, args, joinPoint);
        }

        public abstract MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint);

        MetaHolder.Builder metaHolderBuilder(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
            MetaHolder.Builder builder = MetaHolder.builder()
                    .args(args).method(method).obj(obj).proxyObj(proxy)
                    .defaultGroupKey(obj.getClass().getSimpleName())
                    .joinPoint(joinPoint);
            if (isCompileWeaving()) {
                builder.ajcMethod(getAjcMethodFromTarget(joinPoint));
            }
            return builder;
        }
    }

    private static class CollapserMetaHolderFactory extends MetaHolderFactory {

        @Override
        public MetaHolder create(Object proxy, Method collapserMethod, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
            HystrixCollapser hystrixCollapser = collapserMethod.getAnnotation(HystrixCollapser.class);
            if (collapserMethod.getParameterTypes().length > 1 || collapserMethod.getParameterTypes().length == 0) {
                throw new IllegalStateException("Collapser method must have one argument: " + collapserMethod);
            }

            Method batchCommandMethod = getDeclaredMethod(obj.getClass(), hystrixCollapser.batchMethod(), List.class);
            if (batchCommandMethod == null || !batchCommandMethod.getReturnType().equals(List.class)) {
                throw new IllegalStateException("required batch method for collapser is absent: "
                        + "(java.util.List) " + obj.getClass().getCanonicalName() + "." +
                        hystrixCollapser.batchMethod() + "(java.util.List)");
            }

            if (!collapserMethod.getParameterTypes()[0]
                    .equals(getGenericParameter(batchCommandMethod.getGenericParameterTypes()[0]))) {
                throw new IllegalStateException("required batch method for collapser is absent, wrong generic type: expected"
                        + obj.getClass().getCanonicalName() + "." +
                        hystrixCollapser.batchMethod() + "(java.util.List<" + collapserMethod.getParameterTypes()[0] + ">), but it's " +
                        getGenericParameter(batchCommandMethod.getGenericParameterTypes()[0]));
            }

            Class<?> collapserMethodReturnType;
            if (Future.class.isAssignableFrom(collapserMethod.getReturnType())) {
                collapserMethodReturnType = getGenericParameter(collapserMethod.getGenericReturnType());
            } else {
                collapserMethodReturnType = collapserMethod.getReturnType();
            }

            if (!collapserMethodReturnType
                    .equals(getGenericParameter(batchCommandMethod.getGenericReturnType()))) {
                throw new IllegalStateException("Return type of batch method must be java.util.List parametrized with corresponding type: expected " +
                        "(java.util.List<" + collapserMethodReturnType + ">)" + obj.getClass().getCanonicalName() + "." +
                        hystrixCollapser.batchMethod() + "(java.util.List<" + collapserMethod.getParameterTypes()[0] + ">), but it's " +
                        getGenericParameter(batchCommandMethod.getGenericReturnType()));
            }

            HystrixCommand hystrixCommand = batchCommandMethod.getAnnotation(HystrixCommand.class);
            if (hystrixCommand == null) {
                throw new IllegalStateException("batch method must be annotated with HystrixCommand annotation");
            }
            // method of batch hystrix command must be passed to metaholder because basically collapser doesn't have any actions
            // that should be invoked upon intercepted method, its required only for underlying batch command
            MetaHolder.Builder builder = MetaHolder.builder()
                    .args(args).method(batchCommandMethod).obj(obj).proxyObj(proxy)
                    .defaultGroupKey(obj.getClass().getSimpleName())
                    .joinPoint(joinPoint);

            if (isCompileWeaving()) {
                builder.ajcMethod(getAjcMethodAroundAdvice(obj.getClass(), batchCommandMethod.getName(), List.class));
            }

            builder.hystrixCollapser(hystrixCollapser);
            builder.defaultCollapserKey(collapserMethod.getName());
            builder.collapserExecutionType(ExecutionType.getExecutionType(collapserMethod.getReturnType()));

            builder.defaultCommandKey(batchCommandMethod.getName());
            builder.hystrixCommand(hystrixCommand);
            builder.executionType(ExecutionType.getExecutionType(batchCommandMethod.getReturnType()));
            return builder.build();
        }
    }

    private static class CommandMetaHolderFactory extends MetaHolderFactory {
        @Override
        public MetaHolder create(Object proxy, Method method, Object obj, Object[] args, final ProceedingJoinPoint joinPoint) {
            HystrixCommand hystrixCommand = method.getAnnotation(HystrixCommand.class);
            MetaHolder.Builder builder = metaHolderBuilder(proxy, method, obj, args, joinPoint);
            builder.defaultCommandKey(method.getName());
            builder.hystrixCommand(hystrixCommand);
            builder.executionType(ExecutionType.getExecutionType(method.getReturnType()));
            return builder.build();
        }
    }

    private static enum HystrixPointcutType {
        COMMAND,
        COLLAPSER;

        static HystrixPointcutType of(Method method) {
            return method.isAnnotationPresent(HystrixCommand.class) ? COMMAND : COLLAPSER;
        }
    }

    private static Method getAjcMethodFromTarget(JoinPoint joinPoint) {
        return getAjcMethodAroundAdvice(joinPoint.getTarget().getClass(), (MethodSignature) joinPoint.getSignature());
    }


    private static Class<?> getGenericParameter(Type type) {
        Type tType = ((ParameterizedType) type).getActualTypeArguments()[0];
        String className = tType.toString().split(" ")[1];
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            throw Throwables.propagate(e);
        }
    }

}

https://github.com/dmgcodevil/Hystrix/tree/958ec5d7b4bb967be077a4c2bbcdc71e7a7f5248/hystrix-contrib/hystrix-javanica
在这里插入图片描述

4、通过查看源码找到解决方案

上面这个图片看到:
在这里插入图片描述

在pom.xml文件中加入:

	<!-- https://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-javanica -->
		<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-javanica</artifactId>
			<version>1.5.12</version>
		</dependency>

问题解决OK!

更多系列文章推荐:

  1. Spring Cloud (20) | Spring Cloud Bus 使用kafka消息总线、gitlab添加webhooks实现自动刷新配置
  2. Spring Cloud (19) | Eureka Server 高可用服务注册中心
  3. Spring Cloud (18) | 给Eureka Server加上安全验证
  4. Spring Cloud (15) | Spring Boot、HikariCP、Mybatis和MySQL 配置HikariCP数据库连接池
  5. Spring Cloud (14) | 微服务不能从git/github/gitlab中获取数据库信息 can’t load properties from git/github/gitlab
  6. Spring Cloud (12) | Spring Cloud Zuul网关调用微服务,request请求参数是application/json
  7. Spring Cloud (11) | healthcheck开启健康检查
  8. Spring Cloud (10) | Eureka 各项参数详解
  9. Spring Cloud (8) | 把Spring Boot项目改造成tomcat容器启动
  10. Spring Cloud (7) | Mongodb 微服务
  11. Spring Cloud (6) | spring cloud zuul 跨域问题No ‘Access-Control-Allow-Origin’ header
  12. Spring Cloud (5) | 配置中心 Config Server 配置git or github or gitlab
  13. Spring Cloud (3) | spring cloud bus 消息总线kafka应用
  14. Spring Cloud (1) | java.net.UnknownHostException: eureka-server

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/163996.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!