Этот учебник Mkyong предлагает инициализировать регистраторы следующим образом:
@Controller
public class WelcomeController {
private static final Logger logger = Logger.getLogger(WelcomeController.class);
// etc
}
Предположительно, теперь любой другой используемый вами класс, имеющий регистратор, будет инициализировать свои регистраторы таким же образом.
Мой вопрос - это лучший способ сделать это? Кажется ... повторяющимся.
getLogger()
имя регистратора, чтобы получить.Ответы:
Ваш комментарий говорит, что «многословный» относится к необходимости повторять эту строку кода в каждом классе. Мой первый ответ заключается в том, что добавление двух строк кода (определение переменной плюс оператор импорта) к каждому классу не так уж и сложно. Тем более, что вам нужно только добавить их в классы, которые ведут себя и, следовательно, должны вести журналы. Тем не менее, конкретная строка кода, которую вы используете, подвержена ошибкам копирования-вставки (подробнее об этом позже).
Но, поскольку вы хотите альтернативы, вот несколько, с причинами, по которым вы можете или не захотите их использовать.
Используйте один регистратор для всего приложения
Если вас не волнует, какой класс сообщает, или вы хотите поместить в сообщение весь необходимый контекст, тогда простой одноэлементный регистратор сделает эту работу:
По моему мнению, одно из больших преимуществ каркаса ведения журнала - это наличие контекста, предоставляемого отдельными экземплярами средства ведения журнала - если только для направления сообщений журнала в разные места назначения. Я бы не отказался от этого, просто чтобы сохранить одну строку кода (вам все еще нужен импорт).
Кроме того, это увеличивает многословие в точке использования, что приведет к гораздо большему количеству нажатий клавиш.
Создайте свои регистраторы на месте использования
Я выбрасываю это только потому, что оно исключает переменную. Я не думаю, что мне нужно комментировать это. Хотя это показывает мой предпочтительный метод получения экземпляра регистратора.
Используйте постпроцессор бина, чтобы внедрить регистратор
В вашем примере используется Spring, а Spring позволяет вам подключиться к коду инициализации компонента. Вы можете создать постпроцессор, который проверяет бин на
logger
переменную-член и создаетLogger
экземпляр, когда находит его.Хотя такой постпроцессор занимает всего несколько десятков строк кода, он является еще одной движущейся частью вашего приложения и, следовательно, еще одним потенциальным источником ошибок. Я предпочитаю иметь как можно меньше таких.
Используйте миксин
Scala и Groovy предоставляют черты , которые позволяют вам инкапсулировать поведение. Типичным шаблоном Scala является создание
Logging
признака, а затем добавление его в класс, который требует регистрации:К сожалению, это означает, что вам нужно переключать языки. Если вы не используете Java 8, в этом случае вы можете создать
Logging
интерфейс с «методом по умолчанию»:Теперь, внутри вашего кода класса, вы можете просто использовать
Хотя это легко, у этого есть пара недостатков. С одной стороны, он загрязняет интерфейс каждого класса, который его использует, потому что все методы интерфейса являются открытыми. Возможно, это не так уж и плохо, если вы используете его только для классов, которые создаются и внедряются Spring, особенно если вы используете разделение интерфейса / реализации.
Большая проблема состоит в том, что он должен искать фактический экземпляр регистратора при каждом вызове. Что быстро, но не нужно.
И вам все еще нужно заявление на импорт.
Переместить регистратор в суперкласс
Я повторю: я не нахожу многократные определения логгеров, но если вы это сделаете, я думаю, что это лучший подход к их устранению.
Теперь ваши классы контроллеров наследуются
AbstractController
и имеют доступ кlogger
переменной. Помните, что вы должны поместить@Controller
аннотацию в конкретный класс.Некоторые люди сочтут это извращением наследства. Я попытался смягчить их, назвав класс,
AbstractController
а неAbstractProjectClass
. Вы сами можете решить, есть ли отношения.Другие люди будут возражать против использования переменной экземпляра, а не статической переменной. Статические логгеры IMO подвержены ошибкам копирования-вставки, потому что вы должны явно ссылаться на имя класса;
getClass()
гарантирует, что ваш регистратор всегда правильно.источник
MethodHandles.lookup().lookupClass()
лучше, чемObject.getClass()
?MethodHandles.lookup().lookupClass()
может использоваться для статических переменных, не подвержен ошибкам копирования и вставки и быстр: stackoverflow.com/a/47112323/898747 Это означает дополнительный вход, но мне очень нравятся мои логгеры, находящиеся в статическом состоянии, поэтому, по крайней мере, стоит упомянуть :)Для того, чтобы расширить ответ предоставленного @kdgregory, Groovy обеспечивает
@Slf4j
(groovy.util.logging.Slf4j
выход) из коробки , как аннотация , которая выполняет преобразование AST на классе лавировать его с регистратором , который принимает имя переменногоlog
по умолчанию , если не указано слева.источник