1

spring-mvc コントローラー クラスで Groovy mixin 変換を使用しようとしていますが、Spring は混合されたクラスからリクエスト マッピングを取得しません。

class Reporter {
    @RequestMapping("report")
    public String doReport() {
        "report"
    }
}

@Mixin(Reporter)
@Controller
@RequestMapping("/a")
class AController {
    @RequestMapping("b")
    public String doB() {
        "b"
    }
}

このコードを実行する.../a/bと、URL がマップされて機能しますが、.../a/reportマップされず、HTTP 404 が返されます。デバッグ モードでは、ダック タイピングdoReportでメソッド on にアクセスできます。AController

このタイプのリクエスト マッピングの継承extendsは、使用時に Java クラスで実際に機能します。では、なぜ Groovy では動作しないのmixinでしょうか? mixin変換がメソッドの注釈を転送しないか、ミックスインが処理される前にSpringのコンポーネントスキャナーが機能するかのいずれかだと思います。いずれにせよ、この機能を実現するためのより洗練された方法はありますか (他の理由で AController に Reporter を拡張させたくないので、それはオプションではありません)。

4

2 に答える 2

3

以下は、Groovy ユーザー メーリング リストのGuillaume Laforge (Groovy プロジェクト マネージャー) から得た回答です。

やあ、

Spring MVC の実装は見ていませんが、使用可能なメソッドを見つけるためにリフレクションを使用していると思われます。そして、メソッドを動的に追加する「ミックスイン」は、反射によって見えるものではありません。

私たちは何年にもわたって @Mixin に問題を抱えてきました。修正に向けた努力にもかかわらず、その実装は理想とはかけ離れており、バグだらけです。まもなく非推奨になり、静的 mixin や trait のようなものを導入する可能性があります。これにより、クラスに「実際に」メソッドが追加されます。つまり、doReport() のようなメソッドは、Spring MVC のようなフレームワークで認識されます。 .

Cédric のプロトタイプ ブランチや Grails で本質的にそれを行うもの (つまり、AST 変換による「実際の」メソッドの追加) など、その分野ではすでにいくつかのイニシアチブがあります。確固たる決定は下されていませんが、調査してすぐに提供したいと考えています。

質問に戻りますが、@Delegate を使用して調査できますか? コントローラー クラスに @Delegate Reporter レポーター プロパティを追加します。@Delegate がアノテーションを持っているかどうかは覚えていません。二重チェックはしていませんが、もしそうなら、それは短期的にはあなたにとって良い解決策になるかもしれません.

ギヨーム

@Delegate 変換を使用するだけでは機能しないため、別の提案が必要でした。

もう一度試してみてください...委任されたメソッドのアノテーションを運ぶことについて話したことを思い出しました...そして実際にそれをすでに実装しました。デフォルトではオンになっていないため、@Delegate アノテーションのパラメーターでアクティブ化する必要があります: http://groovy.codehaus.org/gapi/groovy/lang/Delegate.html#methodAnnotations

@Delegate(methodAnnotations = true) で試してみてください。

そして、実際の解決策は次のとおりです。

class Reporter {
    @RequestMapping("report")
    public String doReport() {
        "report"
    }
}

@Controller
@RequestMapping("/a")
class AController {
    @Delegate(methodAnnotations = true) private Reporter = new Reporter

    @RequestMapping("b")
    public String doB() {
        "b"
    }
}
于 2013-06-14T10:37:10.470 に答える
0

アノテーションを使用してリクエストをマップすると、コンテナーが開始されると、デプロイ記述子を手動で記述する代わりに、クラスパスがスキャンされ、アノテーション付きのクラスとメソッドが検索され、内部でマップが構築されます。

スキャナーは、コンパイルされた .class ファイルからメソッドと注釈を読み取ります。おそらく、Groovy mixin は実行時に解決されるような方法で実装されているため、スキャナー ソフトウェアはコンパイルされたバイトコードでそれらを見つけることができません。

この問題を解決するには、コンパイル時にコードを静的にミックスインする方法を見つけて、注釈付きメソッドが実際にクラス ファイルに書き込まれるようにする必要があります。

于 2013-06-14T08:03:42.197 に答える