slf4j - 如何扫描/检查包中的 Java 类以获取 @slf4j 注释
问题描述
groovy 和 Spring 的新手,试图帮助我们的开发团队在我们的框架中使用一些日志记录功能。
我创建了一个 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
背景:@Slf4j
Groovy 编译器使用注解来在编译期间动态创建静态记录器,从而将您保存为 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
仅仅因为它在运行时不存在而帮助您拦截注释。你需要找到另一种方法来实现你想要的。一种这样的方法可能是注释处理,因为它是在编译之前完成的。
推荐阅读
- .net - 类型“AngularFireAuth”错误中不存在属性“auth”
- php - 如何使用 Symfony formbuilder 仅获取实体的特定元素?
- javascript - 如何使用 Moment.js 将日期转换为星期天从 0 开始计数的星期几?
- base64 - 如何在 Gatling 中对密码进行编码?
- java - Gradle Log4j 日志级别
- python-3.x - 处理网页抓取时的超时错误
- spring - 为什么未检测到 Spring Facet 且未在 Framework 下拉列表中列出?
- c++ - 如何调整 Eigen::MatrixXd 的 std::vector 的大小
- jenkins - 如何每 3 小时安排一次 Jenkins 作业但排除特定时间范围
- api - 带有区域的 api 的 Dotnet Core 3.1 端点路由