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

本文介绍了如何使用自定义注解和AOP在Java中实现方法执行超时后的降级处理。作者创建了一个名为`Myannotation`的注解,用于指定方法的执行时间和降级方法。通过`@Around`增强切面,监控带有注解的方法,使用`Future`来控制执行时间。当方法执行超时时,会调用预先定义的降级方法。示例代码展示了注解的使用和整个流程的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.引入.
   最近在使用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();
        }


    }

    /**
     * 执行指定方法并监控执行时间,如果在指定时间内没有执行完毕,则直接抛出异常
     * @param proceedingJoinPoint
     * @param specifyExTime
     * @return
     */
    private void executeSpecialMethod(ProceedingJoinPoint proceedingJoinPoint, int specifyExTime) throws InterruptedException, ExecutionException, TimeoutException {
        Callable<Object> callable = new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                try {
                    proceedingJoinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
                return "success";
            }
        };
        Future<Object> future = threadPool.submit(callable);
        future.get(specifyExTime, TimeUnit.SECONDS);
    }

}

四.代码执行效果.
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员bling

义父,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值