2010-06-14 2 views
3

У меня есть код, который является автономным java-приложением, состоящим из 30 классов.Использование того же log4j logger в автономной java-приложении

Большинство из них наследуется от некоторых других базовых классов.

Каждый класс имеет этот метод, чтобы получить и использовать log4j регистратор

public static Logger getLogger() { 
    if (logger != null) return logger; 
    try { 
     PropertyUtil propUtil = PropertyUtil.getInstance("app-log.properties"); 
     if (propUtil != null && propUtil.getProperties() != null) 
      PropertyConfigurator.configure(propUtil.getProperties()); 
     logger = Logger.getLogger(ExtractData.class); 
     return logger; 
    } catch (Exception exception) { 
     exception.printStackTrace(); 
    } 
} 

А) Мой вопрос, является ли это должно быть переработан к некоторому общему регистратору, который инициализируется один раз и используется по всем классам? Это лучшая практика?

B) Если да, как это можно сделать? Как я могу пропустить журнал?

C) Это фактически используется в коде не как Logger.debug(), а getLogger().debug(). Каково влияние этого с точки зрения производительности?

+0

Возможно, я ошибаюсь, но я не думаю, что PropertyConfigurer.configure() является потокобезопасным, поэтому, если ваш код многопоточен, вызов этого метода getLogger() из нескольких потоков может вызвать проблемы. Лучше всего использовать стандартное использование log4j, как описано Péter Török. –

+0

@matt b - спасибо за указание. я буду проверять использование, так как этот код, возможно, выполнен из нескольких потоков – shinynewbike

ответ

8

A) В Log4J у вас есть иерархии журналов, а не один регистратор. Обычно это сводится к одному журналу на класс, где регистраторы идентифицируются по имени класса. Регистратор инициализируется следующим образом:

private static final Logger logger = Logger.getLogger(MyClass.class); 

Это хорошая практика в том, что она позволяет точно настроить поведение протоколирования для модулей (пакетов) или даже отдельных классов в вашем приложении. Таким образом, вы можете отключить ведение журнала для некоторых пакетов, зайти на уровень INFO в других и войти в систему на уровне DEBUG для некоторых критических классов, например. когда вы хотите поймать ошибку.

B) Тем не менее, если вы хотите один регистратор везде, просто использовать корневой регистратор в каждом классе:

private static final Logger logger = Logger.getLogger(); 

C) для звонков не слишком сложные методы, разница в производительности, вероятно, незначительна, поскольку JIT-компилятор в любом случае будет агрессивно встроен. Для сложных методов это скорее открытый вопрос.

Обратите внимание, что метод, который вы показываете, делает ненужную работу, загружая конфигурацию регистратора - это делается автоматически Log4J, если вы назовете свой файл конфигурации log4j.properties и поместите его в путь к классам. Однако даже если вам нужно использовать нестандартное имя файла конфигурации, вы можете загрузить конфигурацию Log4J в одном месте при запуске и опустить ленивую загрузку регистратора. Тогда останутся

и это обязательно будет встроено в компилятор. Однако вы можете сохранить getLogger, чтобы избежать изменения большого количества кода вызывающего абонента.

Обратите внимание, что getLogger не является public, так как все классы должны иметь свою собственную регистрационную ссылку.

0

Каждый класс может получить его собственный регистратор, как

final static private Logger log = Logger.getLogger("com.company.package.MyClass"); 

Это позволяет настроить параметры log4j класса, который является более гибким, чем стандартный регистратор.

3

A) Зависит, но я думаю, что гранулярность регистраторов для каждого класса является частью полезности использования log4j. Вы можете перенаправить информацию журнала из одного класса, если хотите, или отправить их все в один и тот же файл.

B) Вы не будете проходить регистратор, вы бы просто использовали метод Logger.getLogger() для использования корневого регистратора.

C) Вероятно, невелик с точки зрения производительности. Если он еще не был статичным, опция должна указывать ваш метод getLogger() как final, чтобы предположить, что он должен быть встроен. Ответ Питера здесь лучше, и, как он замечает, если метод достаточно прост, он, скорее всего, будет встроен.

+0

re C: getLogger() уже статичен, поэтому сделать его окончательным будет излишним. –

+0

@ Спасибо, ты прав. –

+0

Объявление (не статического) метода 'final' в любом случае не имеет большого значения - компилятор JIT _knows_ независимо от того, переопределен или нет он в реальном контексте, поэтому он может встраиваться соответствующим образом. –