ivan_070 2024-07-22 14:57 采纳率: 87.5%
浏览 13
已结题

spring反射中抛出异常如果不被包裹

在spring项目中,我有个service会通过method.invoke()调用业务方法,业务方法可能会抛出一些自定义的异常,但是实际运行的时候,自定义异常会被java.lang.reflect.InvocationTargetException包裹上,导致GlobalExceptionHandler无法匹配。请问要如何取消这种包裹

代码示例:


```java
    public void test1() throws NoSuchMethodException {
        Method method = this.getClass().getDeclaredMethod("test2");
        try {
            method.invoke(this);
        }catch (Exception ex){
            System.out.print(ex.getMessage());
        }
    }

    private void test2(){
        throw new RuntimeException("111111");
    }


test2中抛出的异常在test1中变成了java.lang.reflect.InvocationTargetException。其中ex.target才是我抛出的异常。
用debug方式跟踪,在throw 之后,跳到了org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(Object... args),其中抛出的异常被捕捉,而后再次抛出,但是被捕捉的异常已经被包裹了一次,此时的RuntimeException被包裹了两层InvocationTargetException


![img](https://img-mid.csdnimg.cn/release/static/image/mid/ask/11649a43f3074a4b8a12b3b6d3f5d12b.png "#left")
  • 写回答

4条回答 默认 最新

  • GISer Liu 2024-07-22 14:58
    关注

    该回答引用自GPT-3.5, 由博主 GISer Liu 编写:

    问题分析

    在Spring项目中,通过反射调用方法时,如果业务方法抛出自定义异常,这些异常会被java.lang.reflect.InvocationTargetException包裹。这会导致GlobalExceptionHandler无法直接捕获和处理这些自定义异常,因为它们被包裹在InvocationTargetException中。

    解决方案

    为了解决这个问题,我们需要在捕获InvocationTargetException时,提取其内部的实际异常,并重新抛出或处理。这样,GlobalExceptionHandler就能正确地捕获和处理这些自定义异常。

    代码修改

    以下是修改后的代码示例:

    public void test1() throws NoSuchMethodException {
        Method method = this.getClass().getDeclaredMethod("test2");
        try {
            method.invoke(this);
        } catch (InvocationTargetException ex) {
            // 提取实际的异常并重新抛出
            Throwable actualException = ex.getTargetException();
            if (actualException instanceof RuntimeException) {
                throw (RuntimeException) actualException;
            } else {
                throw new RuntimeException(actualException);
            }
        } catch (Exception ex) {
            // 处理其他类型的异常
            System.out.print(ex.getMessage());
        }
    }
    
    private void test2() {
        throw new RuntimeException("111111");
    }
    

    详细解释

    1. **捕获InvocationTargetException**:在test1方法中,我们捕获InvocationTargetException异常。
    2. 提取实际异常:通过ex.getTargetException()方法提取被包裹的实际异常。
    3. 重新抛出异常:如果实际异常是RuntimeException,则直接重新抛出;否则,将其包装在新的RuntimeException中并抛出。

    总结

    通过上述修改,我们确保了在通过反射调用方法时,自定义异常不会被InvocationTargetException包裹,从而使得GlobalExceptionHandler能够正确地捕获和处理这些异常。这样,我们就解决了在Spring项目中反射调用方法时异常被包裹的问题。

    如果该回答解决了您的问题,请采纳!如果没有,请私信联系或评论您的疑惑

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 7月31日
  • 已采纳回答 7月23日
  • 创建了问题 7月22日