Комментарии 18
Для себя отметил, что больше уделено внимания настройке визуального формата (скобки, разделители, отступы и подобное). Но, кажется, даёт меньше гибкости и требует больше внимания со стороны разработчика хотя бы в задаче маскирования. На сколько я понял по описанию, требуется глазами отследить, где логируются данные, которые нужно скрывать. И проконтролировать их скрытие самостоятельно.
Мне показался такой путь трудным и ненадёжным. Поэтому в Eclair можно помимо ручного выбора формата для распечатки привязать
ru.tinkoff.eclair.printer.Printer
к типу аргумента (на весь контекст) и этот принтер будет выполнять свою работу в любом месте приложения, уже без ручного контроля.Пользоваться aspect4log, оговорюсь, не приходилось. И во время разработки Eclair я о таком инструменте не знал, поэтому могу оценивать слишком поверхностно.
ru.tinkoff.eclair.logger.ManualLogger
— это не отдельный бин, а interface, который реализован включенным в автоконфигурацию EclairLogger'ом.В примере приведено внедрение через interface. Default'ный логгер его реализует, но делать это не обязательно.
Если сравнивать с
@Slf4j
, на ум приходят такие отличия:1) Eclair включает имя логируемого метода в имя логгера (не только при ручном логировании, а вообще всегда), например:
ru.tinkoff.eclair.example.Example.simple
Благодаря этому есть возможность настраивать через конфигурацию уровни доступного лога не только для пакета/класса, но и для отдельных методов.
Это бывает полезно, когда точно знаешь, в каком месте нужно повысить подробность лога до DEBUG или TRACE, но включать DEBUG для всего класса нет желания (из-за больших объёмов лога или проседания скорости).
2)
ManualLogger
имеет набор «сахарных» методов, например ManualLogger#warnIfDebugEnabled("some")
.Такой метод может быть полезен, если в логике обрабатывается некоторое предупреждение (warning), которое не слишком важно, но если для текущей локации доступен DEBUG, то его нужно залогировать как WARN.
Того же можно добиться с помощью
@Slf4j
, но менее лаконично: if (log.isDebugEnabled()) { log.warn("some"); }
3) ManualLogger принимает в качестве аргументов
Supplier
'ы. На сколько я понимаю, в зависимости о того, что лежит «под» @Slf4j-логгером, ты не всегда имеешь возможность провернуть «ленивую» инициализацию аргументов.4) В метод
ManualLogger#log
есть возможность передать LogLevel, определяемый динамически. Это тоже для особых ценителей. Не сказать, что сильно важная способность.Если эти способности не востребованы, и достаточно стандартного интерфейса slf4j, а также сам Lombok не является проблемой, вполне можно ограничиться
@Slf4j
.А почему так привязались именно к проксям? Есть же aspectj, там и оверхеда поменьше и ограничений таких как у Proxy нет.
Ну, AspectJ достаточно хорошо тестируется, чтобы ему можно было доверять. Я, честно, чаще на баги в Javac'е пока натыкался, чем на баги в AspectJ.
А время компиляции это вообще пыль, если можно увеличить перфоманс, убрав оверхед.
И кстати, спринг позволяет писать независимые от технологии (Dynamic Proxy или AspectJ) аспекты, зачем же руками прокси писать?
И кстати, спринг позволяет писать независимые от технологии (Dynamic Proxy или AspectJ) аспекты, зачем же руками прокси писать?
Всё спринговое AOP построено на проксях.
Target object: object being advised by one or more aspects. Also referred to as the advised object. Since Spring AOP is implemented using runtime proxies, this object will always be a proxied object.
Т.ч. «оверхед» никуда не денется.
Вот даже по вашей ссылке если перейти и прочитать дальше, то будет видно, что вы не правы =)
One such choice that is relevant to this chapter is that of which AOP framework (and which AOP style) to choose. You have the choice of AspectJ and/or Spring AOP, and you also have the choice of either the @AspectJ annotation-style approach or the Spring XML configuration-style approach. The fact that this chapter chooses to introduce the @AspectJ-style approach first should not be taken as an indication that the Spring team favors the @AspectJ annotation-style approach over the Spring XML configuration-style.
В спринге можно выбрать что будет использоваться Spring AOP или AspectJ (пару аннотаций повесить). Spring AOP поддерживает только небольшой сабсет возможностей AspectJ.
Load Time Weaving
Для @Transactional, кстати, можно выбрать AdviceMode (PROXY, ASPECTJ).
Спринговое AOP специально было разработано так, чтобы не привязываться к конкретной технологии (это так же написано в доке)
Есть паттерн прокси, а есть класс в джаве java.lang.reflect.Proxy. В случае использования CGLIB или AspectJ не будет создан объект класса java.lang.reflect.Proxy. В статье, на которую вы ссылаетесь, написано всего лишь то, что всегда создаётся прокси как паттерн, не как класс из джавы. И в случае с CGLIB и AspectJ это "прокси" без оверхеда, потому что они меняют байткод.
Первоочередной челленжд всё же был в том, чтобы реализовать необходимый функционал и сформировать удобный для использования подход. Вышло ли достаточно удобно — наблюдаем.
Как естественное развитие в сторону снятия ограничений и дальнейшего упрощения работы — будем рассматривать. Тем более, если сообщество проявит интерес к такому преобразованию.
Eclair — Java Spring библиотека декларативного логирования