我有一个客户附加程序:
package com.test.logging;
@Plugin(
name = "xAppender",
category = Core.CATEGORY_NAME,
elementType = Appender.ELEMENT_TYPE)
public class XAppender extends AbstractAppender {
protected XAppender (...) {
super(...)
// some logging to see how many times constructor is called
}
@PluginFactory
public static XAppender createAppender(...) {}
@Override
public void append(LogEvent logEvent) {}
}
和配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" packages="com.microsoft.applicationinsights.log4j.v2, no.test.logging">
<Appenders>
<XAppender name="xAppender"
</XAppender>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="xAppender"/>
</Root>
</Loggers>
</Configuration>
当我在intelliJ中运行代码时,appender构造函数仅被调用一次。如果我使用maven(尝试了maven程序集和shade插件)构建了一个jar,然后运行它,则构造函数(@PluginFactory createAppender)会被调用两次。仅当我初始化一个vertx实例时才会发生这种情况。为什么会发生这种情况?
编辑:我删除了@PluginFactory批注,并且可以看到以下堆栈跟踪。似乎log4j2和io.vertx.core.logging框架都调用了它:
2020-11-05 12:38:20,932 main ERROR Unable to invoke factory method in class com.test.logging.XAppender for element XAppender: java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:234)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:134)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1002)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:942)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:934)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:552)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:241)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:288)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:618)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:691)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:708)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:263)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:602)
at no.Test.main<clinit>(Test.java:26)
并且:
2020-11-05 12:38:21,075 main ERROR Unable to invoke factory method in class com.test.logging.XAppender for element TcAppender: java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender java.lang.IllegalStateException: No factory method found for class com.test.logging.XAppender
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.findFactoryMethod(PluginBuilder.java:234)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:134)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:1002)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:942)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:934)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:552)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:241)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:288)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:618)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:691)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:708)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:263)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:243)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:174)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:669)
at io.vertx.core.logging.Log4j2LogDelegate.<init>(Log4j2LogDelegate.java:31)
at io.vertx.core.logging.Log4j2LogDelegateFactory.createDelegate(Log4j2LogDelegateFactory.java:28)
at io.vertx.core.logging.LoggerFactory.getLogger(LoggerFactory.java:74)
at io.vertx.core.logging.LoggerFactory.getLogger(LoggerFactory.java:67)
at io.vertx.core.impl.AddressResolver.<clinit>(AddressResolver.java:37)
at io.vertx.core.dns.AddressResolverOptions.<clinit>(AddressResolverOptions.java:80)
at io.vertx.core.VertxOptions.<init>(VertxOptions.java:183)
at io.vertx.core.impl.VertxFactoryImpl.vertx(VertxFactoryImpl.java:27)
at io.vertx.core.Vertx.vertx(Vertx.java:75)
at no.Test.main(Test.java:33)
编辑:
我找到了这个问题,但是我不确定潜在的问题:
似乎Vertx.vertx()创建了自己的LoggerContext。从IntelliJ启动项目时,Log4j2似乎了解这一点,并且默认情况下使用以下上下文使用相同的上下文: LogManager.getLogger(ABC.class);或LogManager.getContext(false).getLogger(ABC.class.getName());
当项目以.jar执行时,默认情况下,Log4j2不会获得由Vertx初始化的LoggerContext。可以使用LogManager.getContext(true).getLogger(ABC.class.getName());
修复此问题。注意:在IntelliJ中运行时使用getContext(true)也会导致Log4j2无法获得相同的ContextObject,因此应根据环境(例如IntelliJ或.jar)设置布尔值
注意:在上述两种情况下,Vertx初始化后都会调用记录器。