在开发测试过程中,有时候我们需要抛出一个异常来测试我们的代码.我们往往的做法是在代码中嵌入一段代码来实现,完成功能后再将其注释或者删除,等到下次又要测试的时候,又得重新加入.
int num = ThreadLocalRandom.current().nextInt(100);
if(num%10 ==0){
throw new RuntimeException("随机异常");
}
通过aop,加入注解的方式,以一种优雅的方式,随机参数异常.并可以通过Profile,来指定是否启用.
1.0
public @interface RandomlyThrowsException {
}
@Aspect
public class RandomlyThrowsExceptionAspect implements Ordered {
private final int order;
public RandomlyThrowsExceptionAspect(int order) {
this.order = order;
}
@Override
public int getOrder() {
return order;
}
@Around("@annotation(com.github.superwen0001.practice.exception.RandomlyThrowsException)")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
int num = ThreadLocalRandom.current().nextInt(100);
if (num % 10 == 0) {
throw new RuntimeException("随机异常");
}
return joinPoint.proceed();
}
}
@Configuration
public class ComonConfig {
@Bean
public RandomlyThrowsExceptionAspect randomlyThrowsExceptionAspect() {
final int order = Byte.MAX_VALUE;
RandomlyThrowsExceptionAspect randomlyThrowsExceptionAspect = new RandomlyThrowsExceptionAspect(order);
return randomlyThrowsExceptionAspect;
}
}
@RestController
public class DemoController {
@GetMapping("t1")
@RandomlyThrowsException
public String t1(){
return "t1";
}
}
当访问 http://127.0.0.1:8080/t1, 访问多次出现错误页面
1.1 可以指定异常的类型,异常的message
更进一步,可以指定产生的概率等等
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface RandomlyThrowsException {
String message() default "";
Class<? extends Throwable>[] throwable() default RuntimeException.class;
}
@Aspect
public class RandomlyThrowsExceptionAspect implements Ordered {
private final int order;
public RandomlyThrowsExceptionAspect(int order) {
this.order = order;
}
@Override
public int getOrder() {
return order;
}
@Around("@annotation(com.github.superwen0001.practice.exception.RandomlyThrowsException)")
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
int num = ThreadLocalRandom.current().nextInt(100);
if (num % 10 == 0) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
RandomlyThrowsException randomlyThrowsException = method.getAnnotation(RandomlyThrowsException.class);
String message = randomlyThrowsException.message();
Class[] classes = randomlyThrowsException.throwable();
Class clazz = classes[ThreadLocalRandom.current().nextInt(classes.length)];
//注意,自定义的异常一定要有带一个String参数的构造函数
Constructor c = clazz.getConstructor(String.class);
throw (Throwable) c.newInstance(message);
}
return joinPoint.proceed();
}
}
public class DemoException extends RuntimeException {
public DemoException() {
}
public DemoException(String message) {
super(message);
}
public DemoException(String message, Throwable cause) {
super(message, cause);
}
public DemoException(Throwable cause) {
super(cause);
}
public DemoException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
@RestController
public class DemoController {
@GetMapping("t1")
@RandomlyThrowsException(message = "测试随机异常", throwable = DemoException.class)
public String t1() {
return "t1";
}
}
代码地址: https://github.com/superwen0001/practice/tree/dev/aop-random-exception