2016-09-29 14 views
1

私は何の問題は注釈を付けされていないメソッドのリストを取得することができます...Javaリフレクションは、他のメソッドのパラメータとしてメソッドに渡しますか?

Method[] m = clazz.getDeclaredMethods(); 

今、私は関数に[x]の方法を渡したいと思います。たとえば...

router.get("/").handler(RoutingContext handler) 

私はメソッドリファレンスとしてハンドラに渡したいと思います。

public void myFunction() throws Exception { 

    Router routes = Router.router(...); 

    Handler<RoutingContext> handler = this::myHandler; 
    routes.route("/").handler(handler); 
    routes.route("/someOtherRoute").handler(this::anotherHandler); 

} 

public void myHandler(final RoutingContext rcs) { 
    rcs.doSomething(); 
} 

が、私はそう、私は反射的にそれを見つけて、「ルータ」に追加することができ、機能はmyHandlerに注釈を付けたいと思います。java 8で

我々だけでrouter.get("/").handler(this::myMethod)

更新例を行うことができます。だから、反射して、私は...

を何ら問題は注釈を付けていないし、各1のために私のルータに追加されているメソッドのリストを取得することができますので、

@GET 
public void myHandler(final RoutingContext rcs) { 
    rcs.doSomething(); 
} 

@POST 
public void anotherHandler(final RoutingContext rcs) { 
    rcs.doSomething(); 
} 
...私はいくつかの「ウェブ」anotationsを持っていると言います

私は、リフレクションを使用してこれらのメソッドを一覧表示することができます。クールな問題はありません。しかし、私は上記の例に示すように、router.handler()へのメソッド参照としてそれらを渡したいと思います...

もしあなたがそれをWebフレームワークのために推測していないのであれば、私はそれを私たちは別のものが必要なように野生ではない。それは学習のための笑です。

更新

ルータはタイプのものであり:https://github.com/vert-x3/vertx-web/blob/master/vertx-web/src/main/java/io/vertx/ext/web/Router.java

そして、投手はvertx.io

+0

...反射呼び出しにこだわるあなたが反射で名前で特定のメソッドを取得する方法をお探しですか? – mhasan

+0

いいえ、それは私が知っている。しかし、私はメソッド参照/ラムダを別の関数に渡したいと思っています... – user432024

+1

あなたの質問は実際には[XY問題](http://mywiki.wooledge.org/XyProblem)です。最高の解決策は完全に別のアプローチを使用することです。あなたが現在解決しようとしている方法ではなく、解決しようとしている全体的な問題を教えてください。 –

答えて

2

反射呼び出しを実行するラムダ式を渡すだけで済みます(例:

routes.route("/").handler(rc -> { try { method.invoke(this, rc); } 
    catch (ReflectiveOperationException ex) { throw new RuntimeException(ex);} 
}); 

このジョブを実行します。

また、実際には、メソッド参照と同等のインスタンスを生成することができます。これは、リフレクション操作(および投稿していないHandlerインターフェイス)に関する深い知識が必要です。例えば。起動Consumer<RoutingContext>生成しますmethodあなたが使用することができます。

MethodHandles.Lookup l=MethodHandles.lookup(); 
Consumer<RoutingContext> c=(Consumer<RoutingContext>) 
    LambdaMetafactory.metafactory(l, "accept", 
    MethodType.methodType(Consumer.class, getClass()), 
    MethodType.methodType(void.class, Object.class), l.unreflect(method), 
    MethodType.methodType(void.class, RoutingContext.class)) 
    .getTarget().invoke(this); 

Handler生成するには代わりに、あなたはHandlerの機能メソッドの名前でHandler"accept"Consumerの出現を交換する必要があります。また、Handlerの型パラメータがObject以外の下限を持つ場合は、Object.classを下限の生の型に置き換える必要があります。

documentation of LambdaMetaFactoryは非常に包括的で、より多くの情報を提供related Q&A’s on SOがあるあなたが疑問を持っている場合は、しかし、ちょうど

+0

試してみてください。しかし、otが助けてくれれば...ルータはhttps:// githubです。web/blob/master/vertx-web/src/main/java/io/vertx/ext/web/Router.javaであり、ハンドラもvertxの一部です... – user432024

+1

したがって、 'Handler'メソッド名だけで 'Consumer'と異なります。つまり、' 'accept ''を '' handle "'で置き換える必要があります。 – Holger

+0

両方のソリューションが動作します:) – user432024

0

の一部であり、あなたはメソッドの参照を使用する場合、参照の型は、そのクラスでありますインターフェイスタイプ(具体的には、機能インタフェース)を実装します。あなたのメソッド参照のタイプはHandler<RoutingContext>あるようなあなたの場合には、それが見えます。

Methodを選択した機能インターフェイスに変換する方法を探しているようです。私はそれを行うための直接的な方法を知りませんが、あなたはMethodメートルを持っている場合、あなたが今

public class HandlerFromMethod implements Handler<RoutingContext> { 

    final private Method method; 

    public HandlerFromMethod(Method m) { 
     method = m; 
    } 

    @Override 
    public void apply(final RoutingContext rcs) { 
     method.invoke(null, rcs); 
    } 
} 

ような何かを試すことができ、new HandlerFromMethod(m)Handler<RoutingMethod>として使用できるオブジェクトを作成し、mを呼び出します呼び出されると。

メソッドがインスタンスメソッドの場合、操作するインスタンスを指定するために別のパラメータをコンストラクタに追加し、それをinvokeの最初のパラメータとして使用することをお勧めします。

私はHandlerのメソッドがapply命名されていることを仮定しています。それが他のものなら、上記のコードで名前を変更してください。

免責事項:私はこれをテストしていません。

+1

'Handler'は機能的なインターフェースだと仮定しているので、ラムダ式を使う代わりに通常のクラスに戻す必要はありません。それを使用しない唯一の理由は、必要な例外処理のためにサイズが大きくなりますが、あなたはその部分をコードに残してしまいます。さらに、OPのコンテキストからは、ターゲットメソッドがインスタンスメソッドであることは明らかです。したがって、 'null'をターゲットインスタンスとして渡すことはできません。 – Holger

+0

しかし、別のクラスを使用すると、特に複数回使用される場合、物を読みやすくすることができます。 YMMV。 – ajb

関連する問題