在处理抛出 Throwable 的方法时,我应该避免抛出 Throwable 吗?

Should I avoid throwing Throwable when dealing with a method that throws Throwable?

我有一个 @Aspect 注释 class 正在调用 ProceedingJoinPoint#proceed()。 此方法 throws Throwable 和 class 看起来像这样:

@Aspect
@Component
public class MyClass{

    @Around("@annotation(myAnnotation)")
    public Object myMethod(final ProceedingJoinPoint joinPoint) throws Throwable {
        //some code here
        try {
            return joinPoint.proceed();
        } finally {
            //some more code here
        }
    }
}

在我必须调用另一个方法 throws Throwable 的情况下,myMehtod 可以抛出 Throwable 吗? 我应该避免抛出 Throwable 并以某种方式将其转换为 ExceptionError 吗?

无论哪种情况,我都想知道为什么。谢谢。

不行,扔Throwable不行。错误和未经检查的异常不应该被捕获;错误是严重的或致命的系统问题,而未经检查的异常(通常)会暴露程序员的错误。使用 throws Throwable 声明签名会强制调用者捕获并允许他们抑制不应捕获或抑制的内容。

如果可能,您应该修复 ProceedingJoinPoint.proceed() 方法的签名,但如果您无法控制 class,您自己的代码应该将其包装在更合理的异常中。

如何包装它取决于您对代码调用者的期望。如果任何 Throwable 可能是一个条件,没有人可以做任何事情来纠正或解决,你不妨将它包装在一个未经检查的 RuntimeException 中:

try {
    return joinPoint.proceed();
} catch (Throwable t) {
    throw new RuntimeException(t);
} finally {
    //some more code here
}

如果你想确保调用者优雅地处理所有 Throwable,你应该创建你自己的特定于应用程序的异常 class:

try {
    return joinPoint.proceed();
} catch (Throwable t) {
    throw new JoinPointException(t);
} finally {
    //some more code here
}

异常 class 很简单:

public class JoinPointException
extends Exception {
    private static final long serialVersionUID = 1;

    public JoinPointException(Throwable cause) {
        super(cause);
    }

    public JoinPointException(String message,
                              Throwable cause) {
        super(message, cause);
    }
}

如果您使用 Lombok you can use @SneakyThrows 以便在不声明的情况下重新抛出 Throwable。

@Aspect
@Component
public class MyClass{

    @Around("@annotation(myAnnotation)")
    public Object myMethod(final ProceedingJoinPoint joinPoint) throws Throwable {
        //some code here
        try {
            return proceed(joinPoint)
        } finally {
            //some more code here
        }
    }

    @SneakyThrows
    public Object proceed(ProceedingJoinPoint joinPoint) {
        return joinPoint.proceed();
    }
}

这是我所知道的避免捕获和包装 Throwable 或已检查异常的唯一方法。