切面捕获异常后,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,源码如下:

 
spring配置如下:
 
<bean id="logInterceptor" class="xx.xxx.xxx.LogInterceptor"></bean>
<aop:config>
    <aop:aspect id="logAspectSYS" ref="logInterceptor" order="1">
    <aop:after-throwing method="throwing" throwing="ex" pointcut="execution(public * xx.xxx.xxx..*.*(..))" />
    </aop:aspect>
</aop:config>

切面类如下:

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配置:
<context:component-scan base-package="xx.xx.xxx" />  <!--扫描所有注解的包-->
<aop:aspectj-autoproxy/>                             <!--打开aop注解-->   

切面类如下:

@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"引起的。去掉就好了。
<aop:aspect id="logAspectSYS" ref="logInterceptor" order="1">

 

 
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值