[英]How to use AOP with AspectJ for logging?
我想将“跟踪”消息添加到我所有的公共方法中,如下所示:
public void foo(s:String, n:int) { // log is a log4j logger or any other library log.trace(String.format("Enter foo with s: %s, n: %d", s, n)) ... log.trace("Exit foo") }
现在我想使用 AOP(和字节码检测)自动将所有这些log.trace
添加到我的方法中。 我在考虑AspectJ
。 是否有意义? 您知道任何开源软件,它就是这样做的吗?
我创建了一个简单的方面来捕获公共方法的执行。 这段 AspectJ 代码的核心是切入点定义:
pointcut publicMethodExecuted(): execution(public * *(..));
在这里,我们捕获具有任意返回类型、任意包和任意类、任意数量参数的所有公共方法。
建议执行可以在下面的代码片段中可视化:
after(): publicMethodExecuted() {
System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());
Object[] arguments = thisJoinPoint.getArgs();
for (int i =0; i < arguments.length; i++){
Object argument = arguments[i];
if (argument != null){
System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
}
}
System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}
这个建议使用thisJoinPoint来获取方法签名和参数。 就是这样。 这是方面代码:
public aspect LogAspect {
pointcut publicMethodExecuted(): execution(public * *(..));
after(): publicMethodExecuted() {
System.out.printf("Enters on method: %s. \n", thisJoinPoint.getSignature());
Object[] arguments = thisJoinPoint.getArgs();
for (int i =0; i < arguments.length; i++){
Object argument = arguments[i];
if (argument != null){
System.out.printf("With argument of type %s and value %s. \n", argument.getClass().toString(), argument);
}
}
System.out.printf("Exits method: %s. \n", thisJoinPoint.getSignature());
}
对于更复杂的例子,我会推荐这本书AspectJ: In Action 。
@Loggable
注释和来自jcabi-aspects的 AspectJ 方面对您来说是一种现成的机制(我是一名开发人员):
@Loggable(Loggable.DEBUG)
public String load(URL url) {
return url.openConnection().getContent();
}
根据问题的要求记录进入和退出:
@Loggable(Loggable.DEBUG, prepend=true)
public String load(URL url) {
return url.openConnection().getContent();
}
所有日志都转到 SLF4J。 查看此帖子以获取更多详细信息。
您可以试试这个开源http://code.google.com/p/perfspy/ 。 PerfSpy 是一个运行时日志记录、性能监控和代码检查工具。 它使用 ApsectJ 在运行时围绕您的应用程序代码编织,并记录每个方法的执行时间及其输入参数和值。 它有一个 UI 应用程序,您可以在其中以树的形式查看方法调用及其输入和返回值。 有了它,您可以发现性能瓶颈并了解复杂的代码流。
这是我记录进入、退出和记录方法异常的简单实现
注解
package test;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.TYPE })
public @interface Audit {
}
拦截器
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.logging.Level;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
@Aspect
public class ExceptionInterceptor {
private static final java.util.logging.Logger LOGGER = java.util.logging.Logger.getLogger(ExceptionInterceptor.class.getName());
@Around("execution(* * (..))"
+ " && @annotation(test.Audit)"
)
public Object intercept(final ProceedingJoinPoint point) throws Throwable {
final Method method
= MethodSignature.class.cast(point.getSignature()).getMethod();
String mName = method.getName();
String cName = method.getDeclaringClass().getSimpleName();
LOGGER.log(Level.INFO, "Entering {0}:{1}", new Object[]{cName, mName});
Object out = null;
try {
out = point.proceed();
} catch (Throwable t) {
logExceptions(t, point);
}
LOGGER.log(Level.INFO, "Exiting {0}:{1}", new Object[]{cName, mName});
return out;
}
private void logExceptions(Throwable t, final ProceedingJoinPoint point) {
final Method method
= MethodSignature.class.cast(point.getSignature()).getMethod();
String mName = method.getName();
String cName = method.getDeclaringClass().getSimpleName();
Object[] params = point.getArgs();
StringBuilder sb = new StringBuilder();
sb.append("Exception caught for [");
sb.append(cName);
sb.append(".");
sb.append(mName);
for (int i = 0; i < params.length; i++) {
Object param = params[i];
sb.append("\n");
sb.append(" [Arg=").append(i);
if (param != null) {
String type = param.getClass().getSimpleName();
sb.append(", ").append(type);
// Handle Object Array (Policy Override)
if (param instanceof Object[]) {
sb.append("=").append(Arrays.toString((Object[]) param));
} else {
sb.append("=").append(param.toString());
}
} else {
sb.append(", null");
}
sb.append("]");
sb.append("\n");
}
LOGGER.log(Level.SEVERE, sb.toString(), t);
}
}
如何使用它
@Audit
public void testMethod(Int a,int b, String c){
}
Maven依赖编译
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.7</version>
</dependency>
编织
<plugin>
<groupId>com.jcabi</groupId>
<artifactId>jcabi-maven-plugin</artifactId>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>ajc</goal>
</goals>
</execution>
</executions>
</plugin>
尝试在运行配置中将-javaagent:<path o>aspectjweaver-1.8.7.jar
到您的参数中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.