栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

自定义注解+AOP实现Hystrix中的超时降级

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

自定义注解+AOP实现Hystrix中的超时降级

一.引入.
   最近在使用Hystrix降级组件的时候,好奇它是怎样通过注解实现降级,于是思考后用自己的方式实现超时降级的功能(目前还没有看Hystrix源码,并不一定和其内部实现相同).

二.大体实现思路.

  1. 定义注解,给定执行时间和降级方法
  2. 使用aop监控对应方法执行,对方法进行拦截.
  3. 利用Future对方法执行时间控制,超出指定时间抛出超时异常
  4. 捕获异常,执行降级方法

三.具体实现.
1.工程目录结构

2.启动类
AopAnnotionApplication

@SpringBootApplication
@EnableAspectJAutoProxy
public class AopAnnotionApplication  {

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

}

MyApplicationRunner

@Component
public class MyApplicationRunner implements ApplicationRunner {

    @Resource
    private AnnotationTest annotationTest;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        annotationTest.annotionTest();
        annotationTest.noAnnotion();
    }
}

3.业务类.
Myannotation

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Myannotation {

    int executionTime() default 1;

    String fallbackMethodName();

}

AnnotationTest

@Component
public class AnnotationTest {


    @Myannotation(executionTime=3,fallbackMethodName = "fallbackMethod")
    public void annotionTest(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void fallbackMethod(){
        System.out.println("已执行降级方法");
    }

    public String noAnnotion(){
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Thread.currentThread().getName();
    }
}

AnnotaionAspect

@Component
@Aspect
public class AnnotaionAspect {

    static ExecutorService threadPool= Executors.newFixedThreadPool(2);

    @Pointcut("execution(* com.example.aopannotion.service.*.*(..))")
    public void pt(){}


    @Around("pt()")
    public void aroundAnnotation(ProceedingJoinPoint proceedingJoinPoint){
        //获取类对象
        Object targetObject = proceedingJoinPoint.getTarget();
        //获取方法名称
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        try {
            //通过反射获取方法上是否有注解
            Method method = targetObject.getClass().getMethod(signature.getName(), signature.getParameterTypes());
            Myannotation annotation = method.getAnnotation(Myannotation.class);
            //没有注解不进行时间统计,直接执行方法
            if(annotation == null){
                System.out.println(signature.getName() + "方法无注解,无需检测执行时间.");
                proceedingJoinPoint.proceed();
            }
            //有注解,检测执行时间是否大于指定时间
            else{
                System.out.println(signature.getName() + "方法检测到注解,开始检测执行时间.");
                int specifyExTime = annotation.executionTime();
                String methodName = annotation.fallbackMethodName();
                //使用单独线程执行对应方法,并监控执行时间
                try{
                    executeSpecialMethod(proceedingJoinPoint,specifyExTime);
                    System.out.println(signature.getName() + "方法执行完毕,未超过指定时间:"+specifyExTime+"s");
                }catch (TimeoutException e){
                    //调用方法超时,执行降级方法
                    System.out.println(signature.getName() + "方法执行时间超过指定时间:"+specifyExTime+"s,开始执行降级方法");
                    Method fallbackMethod = targetObject.getClass().getMethod(methodName);
                    fallbackMethod.invoke(targetObject,fallbackMethod.getParameterTypes());
                }catch (Exception e){
                    throw e;
                }
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }


    }

    
    private void executeSpecialMethod(ProceedingJoinPoint proceedingJoinPoint, int specifyExTime) throws InterruptedException, ExecutionException, TimeoutException {
        Callable callable = new Callable() {
            @Override
            public Object call() throws Exception {
                try {
                    proceedingJoinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
                return "success";
            }
        };
        Future future = threadPool.submit(callable);
        future.get(specifyExTime, TimeUnit.SECONDS);
    }

}
 

四.代码执行效果.

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号