4

この問題の理解を深めたいと思っています。回避策は非常に簡単です。つまり、プロキシ/アドバイスがラップされていない別のクラスに構成データを移動しますが、これをよりよく理解することは、将来的に他の関連する問題を回避するのに役立つと思います。提供することができる。

Spring 3.1.0.RELEASE を Spring STS と vFabric tc サーバーで使用しています。@Controller クラスを使用して基本的な小さな REST サーバーを実装しました。それはすべて素晴らしいことですが (本当にそうです)、@Controller も @Transactional であり、それとロード時間の織り込みと vFabric tc サーバーの間で、@Value が壊れます。

@Controller
@RequestMapping("/hello")
public class MyAPI {

    @Value("${my.property}")
    private String prop;
    ...

    @Transactional
    handleRequest(...) ...


}

プロパティ ファイル app.properties:

my.property = SUCCESS

これは JUnit の下で正常に動作し、テストは "SUCCESS" に設定された prop を持つ MyAPI オブジェクトを取得します。しかし、アプリが vFabric に読み込まれると、読み込み時間の織り込みとプロキシが発生すると推測されます。何が起こっても、2 つの MyAPI インスタンスが作成されます。1 つは prop == "SUCCESS" で、もう 1 つは (残念ながら http 要求を処理するものです) prop == "${my.prop}" です。

要するに、私はこれを魔法の失敗と呼んでいます。これは、AOP のようなものを使用する際の私の最大の懸念事項です。STS を使用しても、問題の背後にある原因を追跡する方法や、これが重大なバグであるかどうかを判断する方法がわかりません。バグだとしたらSpringのバグなのか、AspectJなのか、ロードタイムウィーバーなのか、vFabricのバグなのかわからないので、どこにバグレポートを提出すればいいのかもわかりません。

したがって、これを理解するための助けをいただければ幸いです。ありがとう。

4

4 に答える 4

6

私はそれを考え出した。それは確かに、あまりにも多くの魔法でした。

STS で Spring Roo を使用して基本的なアプリ フレームワークを生成し、STS を使用して Roo を除外しました。

Roo が「ベスト プラクティス」として行うことの 1 つは、2 つの Spring コンテキストを作成することです。1 つはアプリ全体用で、もう 1 つはディスパッチャー サーブレットに限定されます。正確な理由はまだわかりませんが、コントローラーなどのプレゼンテーション層が共有されているサービス層に忍び寄らないようにしたいと考えています。これは axtavt hereによってうまく説明されました。これはすべて、STS によって私から隠されていました。

Roo を使用した STS では、WEB-INF ソースは /src/main/resources (META-INF ディレクトリがある場所) の下ではなく、Java ではない /src/main/webapp の下にあると思っていました。 /target ディレクトリのすぐ上にあるため、出力フォルダーと間違えました。

Roo は applicationContext.xml にフィルターを挿入して、axtavt の投稿で説明されているように、アプリケーション コンテキストがコントローラーを構築しないようにしましたが、Roo が生成したクラスのスキャンを排除する別のフィルターも挿入しました。私は両方のフィルターを同時に取り出しました。それらが何のためにあるのかよくわかりませんでしたが、単に Roo の残り物だと思っていました。

そのため、前に説明したように、コントローラーが2回作成されるという問題があります。また、アプリケーション コンテキスト内のものは、applicationContext.xml を使用してプロパティ ファイルを検索しているため、割り当てられたプロパティを取得します。しかし、なぜ両方ともプロパティ セットを取得しなかったのでしょうか。

これにより、不明瞭な webapps フォルダーに戻ります。Roo は WEB-INF フォルダー内に (当然のことながら) web.xml と、webmvc-config.xml ファイルを含む spring フォルダーを配置しました。この構成ファイルは、コントローラーのみをスキャン、作成、およびセットアップするようにセットアップされています。web.xml ファイルは、web アプリが applicationContext.xml を使用するように設定し、dispatcherServlet が webmvc-config.xml を使用するように設定するため、二重の作成を避けるために、applicationContext.xml にフィルターを残す必要がありました。

パズルの最後のピースは、この webmvc-config.xml ファイルでした。これはコントローラーが設定されるコンテキストであるため、プロパティ ファイルを見つけることができるように、そのファイルには <context:property-placeholder/> も構成する必要がありました。

于 2012-04-12T02:50:50.037 に答える
1

まず、# ではなく、$ を使用した表記が正しいです。

元のポスターに関しては、2 つの注釈 (@Controller と @Transactional) の間で競合する動作があると思います。

@Transactional アノテーションを使用すると、実装がプロキシ化されます (エラーを検出してロールバックを開始すると思います)。

これで、コントローラの 2 つのインスタンスが表示されたと言っています。そんなことはあってはなりません。通常、メモリにロードされるコントローラのインスタンスは 1 つだけにする必要があります。

構成ファイルに関連している可能性がありますか、それとも @Transactional の存在とそのプロキシの性質によるものでしょうか?

補足として、私は @Transactional をコントローラー自体で使用することはありませんが、サービスまたは dao のメソッドで使用します。失敗する可能性があり、ロールバックが必要な実際のプロセスがそこにあり、異なるコントローラー/ソースからアクセスできるためです。

よろしく。

于 2012-04-11T13:42:40.527 に答える