我需要在项目的某些包中记录许多类,我无法更改其源代码。所以我需要一个解决方案,我可以指定包名称,并使用 spring aop 将日志记录添加到该包的类而不更改它们,但我不知道我该怎么做。我怎样才能做到这一点?
1 回答
使用 Spring AOP,您只能在将这些类用作 Spring Bean 时记录它们,即使那样,您也只能记录公共方法的执行。
这是@AspectJ 通知中的一个方面(这是与“真正的 AspectJ”和 Spring AOP 兼容的样式,请阅读spring 参考中的差异),您可以在 Spring AOP 和 AspectJ 字节码编织中使用它:
@Aspect
public class LoggingAspect{
@Pointcut("execution(* com.mycompany.myproject.*.*(..))")
public void methodToLog(){
};
@Around("methodToLog()")
public Object logMethod(final ProceedingJoinPoint joinPoint) throws Throwable{
final StaticPart staticPart = joinPoint.getStaticPart();
final String sig =
"" + staticPart.getSignature() + " with args: "
+ Arrays.deepToString(joinPoint.getArgs());
System.out.println("Entering method " + sig);
final Object result = joinPoint.proceed();
System.out.println("Leaving method " + sig);
return result;
}
}
这是一个带有一些方法的愚蠢类:
package com.mycompany.myproject;
public class Dummy1{
public static void main(final String[] args){
final Dummy1 dummy = new Dummy1();
dummy.doSomeStuff();
dummy.doSomeStuffWithSomeArgs("Hello", 123);
}
private void doSomeStuff(){}
public void doSomeStuffWithSomeArgs(final String firstArg,
final int secondArg){}
}
当您在 Eclipse/AJDT 中将此类作为 Java/AspectJ 应用程序启动时,您将获得以下输出:
Entering method void com.mycompany.myproject.Dummy1.main(String[]) with args: [[]]
Entering method void com.mycompany.myproject.Dummy1.doSomeStuff() with args: []
Leaving method void com.mycompany.myproject.Dummy1.doSomeStuff() with args: []
Entering method void com.mycompany.myproject.Dummy1.doSomeStuffWithSomeArgs(String, int) with args: [Hello, 123]
Leaving method void com.mycompany.myproject.Dummy1.doSomeStuffWithSomeArgs(String, int) with args: [Hello, 123]
Leaving method void com.mycompany.myproject.Dummy1.main(String[]) with args: [[]]
要在 Spring AOP 中测试它会涉及更多工作(主要方法方法不起作用,您必须创建一个 ApplicationContext 并注册一个 Dummy1 类型的 bean,您将在其上调用方法),所以我将离开给你,但我很确定不会记录私有方法调用。
如果您下载SpringSource Tool Suite,您将获得很好的方面可视化和测试工具。即使您只想使用 Spring AOP,您也应该阅读AspectJ 书籍。这是一本很棒的书。
顺便说一句:您显然想使用真正的记录器,而不是 system.out。您可以为每个方面定义一个,或者(仅使用真正的 aspectj)您可以将其作为静态成员引入目标类中以获取每个类的日志记录。我认为 AspectJ 的杀手级功能。