log4j ContentAppender null при статическом

#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
    }