【问题标题】:Spring - injecting Log4j logger without explicit specificationSpring - 在没有明确规范的情况下注入 Log4j 记录器
【发布时间】:2018-04-30 12:45:41
【问题描述】:

我正在使用 Spring 基于 XML 的 DI 来创建我的类。

我还在使用 log4j,并且在每个需要它的类中注入 org.apache.log4j.Logger 作为构造函数参数。

所以我在 Spring 配置中有很多条目,如下所示:

<bean id="myClass" class="com.myProject.MyClass">
    ...
    <constructor-arg type="org.apache.log4j.Logger">
        <bean class="org.apache.log4j.Logger" factory-method="getLogger">
            <constructor-arg value="com.myProject.MyClass"/>
        </bean>
    </constructor-arg>
</bean>

类代码:

package com.myProject;

import org.apache.log4j.Logger;

public class MyClass {
    private final Logger logger;

    public MyClass (
            ...
            Logger logger) {
        ...
        this.logger = logger;
    }

    ...
}

虽然它工作得很好,但我想知道是否有可能将记录器的constructor-arg默认为类名,创建的记录器应该传递给谁的构造函数?

例如像这样 solution 用于 Unity DI 和 log4net,它们在 .Net 中有些类似。


更新:

我看到注入 Logger 而不是在类中初始化它的两个原因。

首先,像private final Logger logger = LogManager.getLogger(MyClass.class); 这样的语句通常是复制粘贴的,因此它们很容易在记录器名称中出错。

Moverover,我想用单元测试来介绍错误日志记录,例如将 Logger 的模拟传递给构造函数,然后验证在调用了一些错误操作后 logger.Error 已被调用。

【问题讨论】:

  • 你为什么不使用 private static final Logger LOGGER = LogManager.getLogger(MyClass.class);
  • 如果需要,可以使用项目 Lombok 的注解 @Log 自动注入 logger。这是一个例子:projectlombok.org/features/log
  • @DirkDeyne 我想注入一个记录器,例如在单元测试中模拟它并验证是否记录了错误。
  • 有更好的方法来测试日志是否发生。 how-to-do-a-junit-assert-on-a-message-in-a-logger

标签: java spring dependency-injection log4j


【解决方案1】:

将记录器作为构造函数参数传递有点糟糕。 此外,您反对使用private ...blah... Logger 的论点是似是而非的。

  1. “复制粘贴容易出错。” 真正的复制粘贴技术容易出错, 但是当您希望每个记录器都有一个唯一的名称(以便识别日志消息的来源)时, 您需要在每个类中声明一个记录器。
  2. “我想在单元测试期间模拟我的记录器。” 虽然用模拟替换最终成员变量是不合理的, 用模拟替换非最终成员变量非常容易。 为此, 您应该始终将类级别记录器声明为:private static Logger ...blah。 具体来说, 不要使用最终记录器。 一旦记录器不是最终的, 使用反射将它们替换为模拟。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-16
    • 1970-01-01
    • 2017-04-11
    • 1970-01-01
    • 2013-04-05
    • 1970-01-01
    相关资源
    最近更新 更多