在抛出异常后,切面通知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">