#java #logging #log4j
#java #ведение журнала #log4j
Вопрос:
Когда ConsoleAppender является статическим, я получаю следующую ошибку от log4j:
log4j:ERROR Attempted to append to closed appender named [null].
Пример кода:
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
public class Logging {
private static final PatternLayout layout = new PatternLayout("[%d{dd MMM yyyy HH:mm:ss}] [%t] %-6r %-5p %mn");
private static final ConsoleAppender consoleAppender = new ConsoleAppender(layout);
private Logger logger;
private String filterClass;
private boolean logFlag = false;
public LoggingExample(Class c) {
logger = Logger.getLogger(c);
logger.setAdditivity(false);
logger.removeAllAppenders();
logger.addAppender(consoleAppender);
consoleAppender.activateOptions();
filterClass = c.getName();
}
public log() {
logger.info("this doesn't work when ConsoleAppender is static!");
}
}
Ответ №1:
Это происходит потому, что removeAllAppenders()
удаляет и закрывает все приложения и базовые программы записи. При этом также закрывается средство записи вашего консольного приложения, потому что консольное приложение уже подключено к регистратору по умолчанию, если вы когда-либо создаете более одного экземпляра LoggingExample
.
Комментарии:
1. Но ConsoleAppender не должен быть прикреплен к logger, пока я специально не прикреплю его с помощью addAppender. Мне нужно удалить все другие приложения до этого, чтобы журналы не дублировались. Я не вижу, как закрывается ConsoleAppender.
2. По какой-то причине я думал, что
ConsoleAppender
s являются особенными, но, похоже, это должно сработать, если вы создаете только один экземплярLoggingExample
. Если вы создадите более одного экземпляра, то то, что я сказал, обязательно произойдет, потому что вашconsoleAppender
является статическим.3. Я создаю более одного экземпляра LoggingExample. Однако я подумал, что это будет нормально, потому что регистратор не является статическим.
4. В log4j всегда есть только один регистратор для каждого имени, и поскольку соглашение (как в вашем случае) заключается в присвоении имени класса регистратору, это всегда будет один и тот же регистратор. Именно поэтому люди часто создают регистратор,
private static final
поскольку использование статического регистратора каждый раз приводит к тому же результату, что и вызовLogger.getLogger
.
Ответ №2:
Я полагаю, что это как-то связано с инициализацией layout или ConsoleAppender. Как вы узнаете, не удалось ли создать layout или ConsoleAppender?
Я буду использовать блок статической инициализации для выполнения любой логики, необходимой для обеспечения создания статических объектов:
public class Logging {
private static final PatternLayout layout;
private static final ConsoleAppender consoleAppender;
static { /* code to initialize layout and consoloAppender */}
// Rest of your code
}