主要问题-如果一个方法遇到错误,我想使用Spring AOP来记录该方法的参数,即如果该方法的执行中出现异常,并且该异常被抛出到调用方法。
我能做上面的事情吗?看起来@AfterThrowing记录了调用方法的详细信息,但没有记录被调用的方法(错误实际发生的地方)。
这就是我的
技术堆栈-
- 弹簧套1.3.5
我的@Aspect类-
@Aspect
@Component
public class LoggingAspect {
@AfterThrowing(pointcut = "execution(* com.spicedcider.service..*.*(..))", throwing = "e")
public void logExceptionContext(JoinPoint joinPoint, Throwable e) {
Object[] params = joinPoint.getArgs();
log.error("Exception while executing method below - ");
log.error("[" + joinPoint.getStaticPart().getSignature() + "]");
log.error("Exception message - " + e.getMessage());
log.error("Full stack trace logged further below");
log.error("Params for this method - ");
for (Object object : params) {
log.error(object == null ? "[is null]" : object.toString());
}
}
以上操作效果良好-如果流程如下图所示,
主调用方法
public void executeBusinessLogic(String var1, String var2) {
/* some activities */
String myName = "Spiced Cider";
returnObject = anotherService.executeSubLogic(myName);
/* more activities based on returnObject */
}
支持方法
public Object executeSubLogic(String name) {
/* an exception occurs here and is thrown to executeBusinessLogic() */
}
现在,AOP将其记录如下。
[ERROR] [..LoggingAspect.logExceptionContext] - Exception while executing method below -
[ERROR] [..LoggingAspect.logExceptionContext] - [void executeBusinessLogic()]
[ERROR] [..LoggingAspect.logExceptionContext] - Exception message - <message>
[ERROR] [..LoggingAspect.logExceptionContext] - Full stack trace logged further below
[ERROR] [..LoggingAspect.logExceptionContext] - Params for this method -
[ERROR] [..LoggingAspect.logExceptionContext] - <var1 value>
[ERROR] [..LoggingAspect.logExceptionContext] - <var2 value>
可以看出,它记录的是"调用方法"和相关项目与"被调用方法"——错误实际发生的地方。
我需要这个的原因-这是从调试的角度来看的。当发生异常时,我需要知道传递给发生异常的方法的params。
考虑的备选方案-
- 现在,我可以使用AOP记录每个方法条目和params,但我不想混淆日志/性能,因为我知道只有在出现异常时才需要params
- 当然,我可以用try/catch块在每个方法中记录这一点,但这意味着必须大量重复样板代码
我已经搜索了许多论坛,其中有关于如何让AOP工作等的详细信息,但找不到上面询问/讨论的内容。这是(我能找到的)唯一一篇关于调用与调用的帖子,但不是这个问题的答案——SpringAOP with groovy:getcalledmethod
请让我知道我们是否能做到我想要的/这是否是正确的(或有效的)方式。非常感谢。
如果一切都实现正确,我希望日志输出会出现多次——对于Spring组件中的每个公共非静态方法都会出现一次(!),从而将错误抛出调用堆栈。这真的是你想要的吗?同一个异常记录了多次?不管怎么说,你似乎就是这么想的。
对观察到的行为产生了一些解释:
- 类声明方法
executeSubLogic(..)
是而不是Spring bean/组件。因为您似乎使用的是Spring AOP,而不是完整的AspectJ,所以AOP框架只能拦截Spring组件的公共方法 - 类声明方法
executeSubLogic(..)
是一个Springbean/组件,但它没有实现接口。为了为类(而不是接口)创建一个动态代理,Spring需要CGLIB,但由于某种原因,该lib不在类路径上 - 切入点捕获包
com.spicedcider.service
中的所有方法执行,包括子包,但声明方法executeSubLogic(..)
的类在该包中是而不是