我有以下代码:
package com.mypackage;
public abstract class MySuperClass {
private static final Logger LOGGER = LogManager.getLogger();
protected void demoLog() {
LOGGER.debug("My message")
}
}
package com.mypackage;
public class MyClass extends MySuperClass {
public void executeLog() {
demoLog();
}
}
执行com.mypackage.MyClass#executeLog
方法时,它会打印:
2018-07-24 10:39:04,964 : DEBUG : : com.mypackage.MySuperClass : demoLog : My message
在日志消息中,发射器为com.mypackage.MySuperClass
,但我想将com.mypackage.MyClass
作为发射器。
com.mypackage.MySuperClass
被多个类扩展Class
调用LogManager.getLogger()
来传递getClass()
作为MySuperClass
的参数,因为它是static
。对我来说,使用static
是个好主意,因为实际的实现是在JSF托管Bean中进行的。我该如何实现?
这里有一个类似的问题:Java Logging With Abstract Classes,但这并没有为我提供解决方案。
Logger
中的MySuperClass
定义为private final Logger logger = LogManager.getLogger(getClass());
,则发射器仍为com.mypackage.MySuperClass
。如果我定义
protected abstract Logger getLogger();
在MySuperClass
中并将其实现为
private final Logger logger = LogManager.getLogger(getClass());
@Override
protected Logger getLogger() {
return logger;
}
MyClass
中的发射器是相同的,即com.mypackage.MySuperClass
。
如果我定义
protected abstract Logger getLogger();
在MySuperClass
中并将其实现为
private final Logger logger = LogManager.getLogger(MyClass.class);
@Override
protected Logger getLogger() {
return logger;
}
MyClass
中的发射器是相同的,即com.mypackage.MySuperClass
。
答案 0 :(得分:1)
一种实现方法是将LOGGER
常量迁移到所有叶子子类,然后通过受保护的抽象方法对其进行访问,如下所示:
public abstract class MySuperClass {
protected void demoLog() {
logger().debug("My message");
}
protected abstract Logger logger();
}
public class MyClass extends MySuperClass {
private static final Logger LOGGER = LogManager.getLogger();
public void executeLog() {
demoLog();
}
@Override
protected Logger logger() {
return LOGGER;
}
}
EDIT :我没有看到您提供的链接,现在我注意到我的回答是this answer的类似物,据我所知-这不是您要寻找的解决方案。
好的,所以这个问题的意思(以及“发射器”的含义)是Log4j2 "class" conversion pattern(使用%C
或%class
获得)而不是{{1 }}相关的模式(使用Logger
或%c
获得)。
请考虑与此示例相关的%logger
配置文件:
log4j2.xml
使用此配置运行您的代码时,得到的输出是:
<Appenders>
<Console name="loggerVsClassAppender" target="SYSTEM_OUT">
<PatternLayout pattern="Logger=%logger | Class: %class | %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.mypackage" level="trace">
<AppenderRef ref="loggerVsClassAppender"/>
</Logger>
</Loggers>
使用此配置运行我的代码时,得到的输出是:
Logger=com.mypackage.MySuperClass | Class: com.mypackage.MySuperClass | My message
如您所见,我的代码中使用了适当的Logger=com.mypackage.MyClass | Class: com.mypackage.MySuperClass | My message
,但Logger
保持不变。
现在,这是%class
conversion pattern的摘录:
输出发出以下信息的调用方的全限定类名: 记录请求。 [...]
生成调用方的类名(位置信息)是一种 昂贵的操作,可能会影响性能。谨慎使用。
如您所见,这是从Class
方法的调用站点的堆栈跟踪中检索的类名。
最后,您不能更改此特定值,因为实际上发生了呼叫Logger.debug
。但是,您可以要做的是将MySuperClass
转换模式替换为%class
转换模式以获得预期的结果。
答案 1 :(得分:-1)
不要使其变为静态。记录器在“相同密钥”之间共享,因此它们将在同一类的实例之间共享。