groovy和Spring的新手试图帮助我们的Dev团队在我们的框架中使用一些日志记录功能。
我创建了一个MethodLogging Aspect来记录任何具有@Loggable注释的类的方法执行时间。
但是,作为第二阶段,我需要确定给定包中的类是否使用@slf4j注释并执行slf4j日志记录功能而不是@Loggable。
这是方面代码
import groovy.util.logging.Slf4j
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.context.annotation.Configuration
@Aspect
@Slf4j
public class LoggingAspect {
// This is a Logging Aspect for the Loggable annotation that calculates
// method runtimes for all methods under classes annotated with @Loggable
@Around('execution (* *(..)) && @within(com.zions.common.services.logging.Loggable)')
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object proceed = joinPoint.proceed();
long executionTime = System.currentTimeMillis() - start;
log.info("${joinPoint.getSignature()} executed in ${executionTime}ms");
return proceed;
}
}
这是@Loggable注释代码
package com.zions.common.services.logging
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
// Logging annotation to be used at class level
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {}
任何有关如何处理这项工作的想法或资源都将受到赞赏。
原则上拦截@Slf4j
将与您自己的自定义注释相同,如果(并且仅当)@Slf4j
在运行时期间仍然存在于字节代码中。但事实上并非如此。它有SOURCE
保留,你可以在annotation source code看到。
背景:Groovy编译器使用@Slf4j
注释,以便在编译期间动态创建静态记录器,以便将您保存为Groovy类中的用户样板代码。如果你反编译这个类......
package de.scrum_master.stackoverflow
import groovy.util.logging.Slf4j
@Slf4j
class FooBarZot {
void test() {
log.info("test")
}
}
......你会看到这样的事情:
package de.scrum_master.stackoverflow;
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FooBarZot implements GroovyObject {
private static final transient Logger log;
public FooBarZot() {
CallSite[] var1 = $getCallSiteArray();
super();
MetaClass var2 = this.$getStaticMetaClass();
this.metaClass = var2;
}
public void test() {
CallSite[] var1 = $getCallSiteArray();
var1[0].call(log, "test");
}
static {
Object var0 = $getCallSiteArray()[1].call(LoggerFactory.class, "de.scrum_master.stackoverflow.FooBarZot");
log = (Logger)ScriptBytecodeAdapter.castToType(var0, Logger.class);
}
}
因此,AspectJ不会帮助您拦截@Slf4j
注释,因为它在运行时不存在。你需要找到另一种方法来实现你想要的。一种这样的方法可能是注释处理,因为它是在编译之前完成的。