【问题标题】:Dynamically logging in spring framework在spring框架中动态记录
【发布时间】:2017-10-27 19:02:30
【问题描述】:

目前我有一个 spring boot 应用程序,对于每个类,如SampleClass,我想要一个日志,我需要像这样初始化记录器:

private static Logger log = LoggerFactory.getLogger(SampleClass.class);

这意味着我们需要将类名静态发送到getLogger 方法。 我正在考虑创建一个可记录的接口,每次一个类实现这个接口时,它都会动态地找到类名并使用正确的类名将日志正确地写入输出流。 我用谷歌搜索找到一个合适的解决方案,但每个示例都专门在编译时发送类名。春天有这个能力吗?

【问题讨论】:

  • 不,但我创建了一个接口 ILoggable,并以链接中提到的相同方式创建了一个日志对象。创建了一个 Log 类并实现了 ILoggable。当我在 Log 类中使用日志对象时,输出表明该日志属于 ILoggable 而不是 Log 类。输出类似于“c.c.c.service.ILoggable:test”而不是“c.c.c.service.Log:test”
  • 您有 2 个选项:使用 private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()) 作为您的日志定义,您可以在 IntelliJ Idea 中将其声明为实时模板(Eclipse 有类似的东西),然后在输入模板词时,IDE 将替换这个词与propper代码,或使用项目Lombok并在类级别定义一个简单的@Log, @Slf4j, ...注释
  • 我很难理解您正在解决的确切问题或您想要用于您的应用程序的用例。是您不想创建静态 Logger 字段还是不想在代码中输入SimpleClass.class?通过已经描述了一个潜在的解决方案,很难找到一个正确的答案来满足您的问题/用例。
  • 我不想每次在我的代码中需要时都输入它。即使使用 MethodHandles.lookup().lookupClass()‌​ 或 this.class 我也需要定义它。这是一个到处重复的样板代码。

标签: java spring logging spring-boot slf4j


【解决方案1】:

我建议在你的项目中使用 Lombok @log varient,它会在编译时自动设置

如果您使用 slf4j,请使用 @Slf4j

这是最好的方法,甚至在某些项目内部使用 spring

【讨论】:

  • 这可能是一个很好的解决方案。我需要在类中定义一个日志变量还是添加它?
  • 还有IDE如何处理它。他们是否知道 log 和 getter/setter 等变量,或者我需要做一些额外的工作?
  • 在IDE中添加lombok后双击jar,它会询问IDE位置,然后设置它。在干净启动 IDE 之后,它将自动获取值
【解决方案2】:

创建一个新的@Log注解。

@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {}

现在实现BeanPostProcessor,它为我们提供了postProcessBeforeInitialization 方法,它允许我们在初始化之前管理一个bean。我们搜索@Log注解并使用LoggerFactory注入一个实现。

@Component
public class LoggerPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                Logger log = LoggerFactory.getLogger(bean.getClass());
                ReflectionUtils.makeAccessible(field);
                field.set(bean, log);
            }
        }, new ReflectionUtils.FieldFilter() {
            @Override
            public boolean matches(Field field) {
                return field.isAnnotationPresent(Log.class);
            }
        });
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

并在字段级别使用@Log 注解来描述我们要注入记录器。

@Log
private Logger logger;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    相关资源
    最近更新 更多