创建MyHystrixCommand
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyHystrixCommand {
/**
* 默认超时时间
* @return
*/
int timeout() default 1000;
/**
* 回退方法
* @return
*/
String fallback() default "";
}
MyHystrixCommandAspect(Hystrix实现是基于AOP实现)
@Component
@Aspect
public class MyHystrixCommandAspect {
ExecutorService executorService= Executors.newFixedThreadPool(10);
@Pointcut(value = "@annotation(MyHystrixCommand)")
public void pointCut(){}
@Around(value = "pointCut()&&@annotation(hystrixCommand)")
public Object doPointCut(ProceedingJoinPoint joinPoint,MyHystrixCommand hystrixCommand) throws InterruptedException, ExecutionException, TimeoutException, NoSuchMethodException,
InvocationTargetException, IllegalAccessException {
int timeout=hystrixCommand.timeout();
//前置的判断逻辑
Future future=executorService.submit(()->{
try {
return joinPoint.proceed(); //执行目标方法
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return null;
});
Object result;
try {
result=future.get(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
future.cancel(true);
// ?
if(StringUtils.isBlank(hystrixCommand.fallback())){
throw e;
}
//调用fallback
result=invokeFallback(joinPoint,hystrixCommand.fallback());
}
return result;
}
private Object invokeFallback(ProceedingJoinPoint joinPoint,String fallback) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
MethodSignature signature=(MethodSignature)joinPoint.getSignature();
Method method=signature.getMethod();
Class<?>[] parameterTypes=method.getParameterTypes();
//以上是获取被代理的方法的参数和Method
//得到fallback方法
try {
Method fallbackMethod=joinPoint.getTarget().getClass().getMethod(fallback,parameterTypes);
fallbackMethod.setAccessible(true);
//完成反射调用
return fallbackMethod.invoke(joinPoint.getTarget(),joinPoint.getArgs());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
测试
@RestController
public class MyHystrixController {
@Autowired
RestTemplate restTemplate;
@MyHystrixCommand(fallback = "fallback",timeout = 3000)
@GetMapping("/hystrix/test")
public String test(){
return restTemplate.getForObject("http://localhost:8082/orders",String.class);
}
public String fallback(){
return "请求被降级";
}
}