多くの場合、複数の Web アプリケーションで単一のアプリケーション コンテキストへのアクセスを共有したいと考える人がいます。その方法については、ここなどで説明されています。
この質問は反対です: 単一の Web アプリケーション内に複数のアプリケーション コンテキストを持つことです。通常、これは簡単です。作成して使用するだけです。
ただし、次のように、Spring の側面で静的変数が原因でそれが不可能になる状況がいくつかあります。
- 2 つのアプリケーション コンテキスト X と Y があり、どちらも注釈
MyBean
を持つを作成します@Transactional
- X と Y の両方に独自のトランザクション マネージャーが含まれています
- X と Y の両方に
<tx:annotation-driven mode="aspectj"/>
宣言があります - ビルド時の AspectJ ウィービングを行っています
この場合の問題は<tx:annotation-driven mode="aspectj"/>
、実際には次のように Bean に変換されることです。
<bean class="org.springframework.transaction.aspectj.AnnotationTransactionAspect"
factory-method="aspectOf"/>
AnnotationTransactionAspect
これは、静的変数に格納されたシングルトンである のアスペクト オブジェクトを返すことに注意してください。AnnotationTransactionAspect
extendsTransactionAspectSupport
には、トランザクション マネージャーをキャッシュするなどのインスタンス フィールドが含まれます。
AnnotationTransactionAspect
その結果、X と Y の Bean が完全に分離されていても、アスペクト シングルトンの同じインスタンス フィールドをめぐって争うことになります。これにより、誰かが間違ったトランザクション マネージャを取得するため、たとえば「進行中のトランザクションはありません」という例外が発生します。
同じことが で起こり@Configurable
ます: Bean を構成するために使用される Bean ファクトリは、静的変数に格納されます (「参考文献」を参照AnnotationBeanConfigurerAspect.beanConfigurerSupport
)。@Transactional
AspectJ はで回避できますが、 では回避できないため、これはより大きな問題です@Configurable
。
私は3つの解決策を考えることができます:
- アスペクトの使用をやめる
- 自分の側面を書く
- X と Y を作成するスレッドで新しいコンテキスト クラス ローダーを作成/設定する
私は本当に好きなので、オプション#1は悪いです@Configurable
。
オプション #2 は面白くないようです。
オプション#3は簡単な方法のようです。
では、オプション #3 はどのように機能するのでしょうか? これは私が曖昧になるところです。Spring クラスを X と Y の異なるクラス ローダーにロードする必要があります。これは、コンテキスト クラス ローダーがその親 (Web アプリケーション クラス ローダー) などに正常に委任できないことを意味します。これをどのように設定しますか?
ありがとう。