Spring Loggerの入手方法

Spring IoCコンテナを使用してアプリケーションを開発するとき、誰もが「より正確で美しい」ロガーを作成する方法を疑問に思ったと思います。 この出版物では、この問題を解決するいくつかの例を挙げたいと思います。



解決策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"); } ... }
      
      





適切な修飾子を使用して目的のロガーを取得します。

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





ほとんどの場合、このソリューションで十分であり、コンテナの完成した手段のみを使用します。 このソリューションの欠点の1つは、新しいロガーを追加するときに、常に新しいBeanを宣言する必要があることです。 もっと普遍的な方法はありますか?



決定4



特別な注釈を使用してコンテナからロガーを取得します。これをロギングと呼びましょう。

 @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(); } ... }
      
      





このソリューションはより普遍的ですが、注釈を追加で宣言し、そのプロセッサを作成する必要があります。



おわりに



友人、コメントでこの問題を解決するための選択肢を提案してください、私はとても幸せです!



GitHubで入手可能なサンプルソースコード



All Articles