and に深刻な問題がTomcatLoadTimerWeaver
ありLog4j
、解決方法がわかりません。
私は以下を使用しています:
- トムキャット 8
- 春のフレームワーク 4.1.2
- Log4j 2.1
- SLF4J 1.7.7
- トップリンク 2.5.2
すべてのロギングは SLF4J にルーティングされ、Log4j 2.1 をロギング バックエンドとして使用しています。web.xml
Log4j は、log4jConfiguration
context-paramで指定された非標準の場所から構成ファイルを取得するように構成されています。はLog4jServletContainerInitializer
、webapp の開始時に Log4j を適切に構成します。Spring がTomcatLoadTimeWeaver
.
私はEclipseLinkでロードタイムウィービングを使用したいので、これをアプリケーションコンテキストに追加しました:
<context:load-time-weaver/>
問題は次のとおりです。Spring がTomcatLoadTimeWeaver
Tomcat の にトランスフォーマーを追加して を登録すると、その後 SLF4J を介して何かをログに記録しようとすると、Log4j が暗黙的に再初期化されます。構成ファイルが標準の場所 (= のルート) にないためです。WebappClassLoader
クラスパス) エラーが表示されます:
log4j2 構成ファイルが見つかりません
その瞬間から、すべてのログ呼び出しが適切に (= MY で指定した方法でlog4j.xml
) 処理されなくなり、Commons Logging と JUL 用の SLF4J+Log4j+bridges の慎重な構成が完全に壊れてしまいます。
クラス ローダー トランスフォーマーを追加すると、Log4j で何かがリセットされているようです。そのため、それ自体を再構成する必要があります。この問題をよりよく理解するために数時間を費やしましたが、Log4j の深い知識がなければ簡単ではありません。内部。
mylog4j.xml
をlog4j2.xml
クラスパス ルートに移動することは (展開上の理由から) 簡単にできることではありません。
おそらく、ロード時間ウィーバーの初期設定 (Log4j が初めて設定される前) でうまくいくかもしれませんが、通常、Log4j は Spring 自体の前に設定する必要があるため、その方法はわかりません。
どんな提案でも大歓迎です。
詳細
DefaultContextLoadTimeWeaver
実際には、Spring の( を運ぶTomcatLoadTimeWeaver
) が初期化されるときは問題は発生しませんが、EclipseLink でLocalContainerEntityManagerFactoryBean
を設定するために使用されるEntityManagerFactory
が初期化されるとき (つまり、が呼び出されるときorg.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet()
) に発生します。 EclipseLinkによるorg.springframework.context.weaving.DefaultContextLoadTimeWeaver.addTransformer(ClassFileTransformer)
ネイティブの実際の作成(によってトリガーされます)。そのため、私の回避策は、の初期化をインターセプトするを登録し、強制的に再度実行して、webapp 設定で Log4j を再構成することでした。しかし、これらの Log4j クラスはデフォルトのメソッドと保護されたメソッドでいっぱいであり、これを機能させるにはリフレクションを使用して Bean ポスト プロセッサをパッケージに配置する必要があったため、私は恐ろしいハックに終わりました。EntityManagerFactory
org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory()
BeanPostProcessor
LocalContainerEntityManagerFactoryBean
org.apache.logging.log4j.web.Log4jWebInitializerImpl.start()
org.apache.logging.log4j.core
よりスマートなソリューション/提案/代替アプローチを歓迎します。
本当の原因
システム全体をさらにデバッグし、この問題の原因を突き止めました。このためにLOG4J2-903を開きました。つまり、Log4j はクラス ローダーのtoString()
値を使用して、マップ内の現在のログ コンテキストを検索します。トランスフォーマーを登録するとTomcatのWebappClassLoader.toString()
メソッドが変更されるため、Log4jは以前に構成されたコンテキストを取得できず、EclipseLink + Springがロードタイムウィーバートランスフォーマーを登録するとすぐに新しいコンテキストを作成します... :-(