Как в Spring logger получить

Разрабатывая приложения используя IoC-контейнер Spring думаю каждый задумывался, а как же «правильнее и красивее» создать логгер. В данной публикации хочу привести несколько примеров решения данной задачи.

Решение 1

Получаем логгер напрямую через LoggerFactory:

@Component public class MyBean {     private static final Logger log = LoggerFactory.getLogger("application");     ... } 

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

Решение 2

Получаем логгер из контейнера при помощи Autowired:

@Component public class MyBean {     @Autowired     private Logger log;     ... } 

Для этого в конфигурации Spring объявляем Bean:

@EnableAutoConfiguration @ComponentScan public class ApplicationConfiguration {     @Bean     public Logger logger(){         return LoggerFactory.getLogger("application");     } ... } 

В данном решении задача по созданию логгера возложена на сам контейнер и укладывается в идеологию IoC, но что же делать, если логгеров в приложении должно быть больше одного?

Решение 3

Объявляем каждый логгер в виде отдельного Bean:

@EnableAutoConfiguration @ComponentScan public class ApplicationConfiguration {     @Bean     @Primary     public Logger logger(){         return LoggerFactory.getLogger("application");     }      @Bean(name = "loggerBean")     public Logger loggerBean(){         return LoggerFactory.getLogger("loggerBean");     } ... } 

Получаем нужный логгер используя соответствующий Qualifier:

@Component public class MyBean {     @Autowired     private Logger log;     @Autowired     @Qualifier("loggerBean")     private Logger log2;     ... } 

Данное решение является достаточным в большинстве случаев, и использует только готовые средства контейнера. Одним из минусов данного решения является то, что при добавлении нового логгера всегда придется объявлять новый Bean. Есть ли более универсальный способ?

Решение 4

Получаем логгер из контейнера при помощи специальной аннотации, назовем ее Logging:

@Component public class MyBean {     @Logging     private Logger log;     @Logging("loggerBean")     private Logger log2;      ... } 

Для это собственно необходимо объявить аннотацию:

@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Logging {     String value(); } 

Данная аннотация будет указывать контейнеру на то, что необходим логгер с именем переданным в параметр value. Если данный параметр не указан, то логгер будет получен по классу компонента, в нашем случае MyBean.
Отлично, но контейнер не умеет обрабатывать нашу аннотацию. Давайте его научим, для этого создадим процессор:

public class LoggingAnnotationProcessor implements BeanPostProcessor {     @Override     public Object postProcessBeforeInitialization(Object bean, String beanName) {         Class clazz = bean.getClass();         do {             for (Field field : clazz.getDeclaredFields()) {                 Logging annotation = field.getAnnotation(Logging.class);                  if (annotation!= null) {                     boolean accessible = field.isAccessible();                     field.setAccessible(true);                     try {                         if(!annotation.value().isEmpty()){                             field.set(bean, LoggerFactory.getLogger(annotation.value()));                         } else {                             field.set(bean, LoggerFactory.getLogger(clazz));                         }                     } catch (IllegalAccessException e) {                         LoggerFactory.getLogger(this.getClass()).error(e.getMessage(), e);                     }                     field.setAccessible(accessible);                 }             }             clazz = clazz.getSuperclass();         } while (clazz != null);         return bean;     }     @Override     public Object postProcessAfterInitialization(Object bean, String beanName) {         return bean;     }  } 

И объявим процессор в конфигурации Spring:

@EnableAutoConfiguration @ComponentScan public class ApplicationConfiguration {     @Bean     public LoggingAnnotationProcessor loggingAnnotationProcessor(){         return new LoggingAnnotationProcessor();     } ... } 

Данное решение является более универсальным, но необходимо дополнительно объявить аннотацию и написать для нее процессор.

Заключение

Друзья, предлагай в комментариях ваши варианты решения данной задачи, буду рад очень рад!

ссылка на оригинал статьи https://habrahabr.ru/post/276729/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *