切面捕获异常后,controller无法捕获,java.lang.IllegalStateException: No MethodInvocation found: Check that an AOP

在抛出异常后,切面通知AfterThrowing捕获过异常,Controller就无法捕获Service抛出的异常类型,但可以捕获Exception或Throwable,获取异常信息提示如下:
 
java.lang.IllegalStateException: No MethodInvocation found: Check that an AOP invocation is in progress, 
and that the ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, 
note that advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! 

当切点service方法抛出异常后,切面类LogInterceptor 的throwing方法会正常执行,但Controller里却无法捕获ValidateException 异常,通过捕获Exception异常后,报出文上错误信息,经查看源码发现,是源码ExposeInvocationInterceptor类中抛出了新异常IllegalStateException,源码如下:

切面捕获异常后,controller无法捕获,java.lang.IllegalStateException: No MethodInvocation found: Check that an AOP_第1张图片
 
spring配置如下:
 


    
    
    

切面类如下:

public class LogInterceptor {

    static Log logger = LogFactory.getLog(LogInterceptor.class);

    public void throwing(JoinPoint joinPoint, Throwable ex) {
        StackTraceElement[] stack =  ex.getStackTrace();
        logger.error("异常信息:" + (ex.getMessage() == null ? "" : ex.getMessage()));  
        logger.error("{");
        logger.error("\t" + ex.getClass().getName());
        for(int i = 0; i < stack.length; i++){
            logger.error("\t" + stack[i]);
        }
        logger.error("}");
    }
}

Service切点方法如下:

 
public int saveFinancialPlan(String applyIds,Double amount,Integer days,Double    interest,Integer raiseDays,Integer releaseType,Date releaseTime)  throws ValidateException{
    throw new ValidateException("发生异常了");
}

Controller方法如下

@RequestMapping(value = "saveFinancialPlan")
public @ResponseBody OperateResult saveFinancialPlan(String applyIds,Double amount,Integer days,Double interest,Integer raiseDays,Integer releaseType,Date releaseTime, Model model){
   try {
    financePlanService.saveFinancialPlan(applyIds,amount,days,interest,raiseDays,releaseType,releaseTime);
   } catch (ValidateException e) {
      return new OperateResult(OperateResultType.Error,e.getMessage());
   }
   return new OperateResult(OperateResultType.Success);
}

研究很久也没弄清原因。可以肯定,配置方面没有问题。

 
但,问题总要解决啊,抱着试试的态度,居然奇迹般的解决了。解决办法就是,去掉所有xml配置的切面编程,改用AspectJ注解的方式。具体如下
 
xml配置:
  
                                

切面类如下:

@Component
@Aspect
public class LogInterceptor {

    static Log logger = LogFactory.getLog(LogInterceptor.class);

    @Pointcut("execution(public * xx.xxx.xxx..*.*(..))")
    public void pointcut(){}

    @AfterThrowing(pointcut = "pointcut()",throwing = "ex")
    public void throwing(JoinPoint joinPoint, Throwable ex) {
        StackTraceElement[] stack =  ex.getStackTrace();
        logger.error("异常信息:" + (ex.getMessage() == null ? "" : ex.getMessage()));  
        logger.error("{");
        logger.error("\t" + ex.getClass().getName());
        for(int i = 0; i < stack.length; i++){
            logger.error("\t" + stack[i]);
        }
        logger.error("}");
    }
}

如此,就解决了问题,再也没有报上文的错误,切面类也很好的实现了功能。

但,为什么xml配置的切面编程就无法实现呢?欢迎大神解答,多谢!
 
补充:
多年以后回看这个问题,觉得那个时候的自己果然很菜啊,究其原因,是xml配置里的order="1"引起的。去掉就好了。

 

 

你可能感兴趣的:(异常解决)