33286


JavaEEのInterceptorを使っています。  
Interceptの対象クラス（メソッドではない）に対してInterceptorのアノテーションを付けたいのですが、実際にInterceptしたいのは対象クラスの`public`メソッドのみです。  
従って、`@AroundInvoke`で受け取った`InvocationContext`からMethodを取得し、それが`public`かどうかをチェックしたいと考えています。  
ただ、Methodクラスにそれっぽいメソッドを見つけることができませんでした。  
何を見ればそれをチェックできるでしょうか？  
あるいは、`public`メソッドのみを対象にInterceptできるような手段があれば、そのほうが良いです。

【追記】  
実験してみたところ、そもそも`private`メソッドにはInterceptできませんでした。  
それどころか、`public`だとしても、「別のクラスから呼ばれた時」しかInterceptできないように見えます。  
（対象クラス内部から自身の`public`メソッドを呼んだ場合にはInterceptされない）

「別のクラスから呼ばれた時しかInterceptされない」という仕様なのであれば、そもそも`public`かどうか調べなくて良いので、ちょうど良いのですが、この認識は正しいでしょうか？


CC BY-SA 3.0
2017-03-13T03:42:34.913
33282
2017-03-13T06:51:00.190
2017-03-13T03:55:02.587
8078
8078
question
java-ee
Interceptorで取得したMethodがpublicかどうか調べる方法


**_この認識は正しいでしょうか？_**

**_「別のクラスから呼ばれた時しかInterceptされない」_**
と言うのは、あなたが調べられた範囲の状況だけを説明するには十分なのですが、必ずしも正確とは言えません。

別のクラスから普通にデフォルトコンストラクタを使ってインスタンス化した場合には、publicなメソッドであろうと(と言うか、publicなメソッドしか呼べませんが)、Interceptされないはずです。

実はCDI管理ビーンがInjectされる場合のインスタンスは、元のクラスそのままのインスタンスではなく、元のクラスをラップした特殊なプロキシクラス(通常は元クラスのサブクラス)のインスタンスになっています。そのプロキシクラス内で、Interceptorのインスタンスと紐づけて、InterceptされるべきメソッドをオーバライドすることでInterceptの仕組みが実現されています。

従って「CDI管理ビーンと同様の機構でインスタンスの生成と初期化が行われた時しかInterceptされない」と言った方がより正確ですね。

どちらにしろprivateメソッドのことは考えなくて良い、と言う点では同じですが、実は別のクラスのインスタンスだということは意識しておいて損はないでしょう。


CC BY-SA 3.0
2017-03-13T04:56:45.993
33286
2017-03-13T04:56:45.993
13972
33282
answer


[Interceptors仕様書(リンク先PDF)](https://java.net/downloads/interceptors-
spec/interceptor-1-2-mrel.pdf)の冒頭の一文

> Interceptors are used to interpose on business method invocations [後略].

の通り、`Interceptors`は`business method`呼び出しに介入する仕組みです。

ここでの`business method`とは、[The Java EE Tutorial: 34.1.2.2 Business
Methods](https://docs.oracle.com/javaee/7/tutorial/ejb-
basicexamples001.htm#BNBOH)で説明されているものです。  
他のオブジェクトが自EJB(やCDI
Bean)をインジェクトして利用してもらうために定義したメソッドで、そうであるためには明らかに`public`である必要があります(補足:リンク先にはそれ以外の条件も記載があります)。  
ただしインターセプトされるのは`public`だからではなく、`business method`呼び出しだからです。

* * *

> 別のクラスから呼ばれた時しかInterceptされない

自クラスのインスタンスをインジェクトしてそのオブジェクトの`business method`を実行すればインターセプトされますので、真か偽かで言うと偽です。  
が、これは今回の質問からすると本質的な話ではないと思います。

[code]

    @Stateless
    @LocalBean
    @Interceptors(MyInterceptor.class)
    public class MyBean {
    
        @EJB
        private MyBean myBean;
    
        public void exec1() {
            // exec2の呼び出しもインターセプト対象
            // つまりexec1を呼ぶと計2回インターセプトされる
            myBean.exec2();
        }
    
        public void exec2() {
        }
    }
    
[/code]


CC BY-SA 3.0
2017-03-13T06:51:00.190
33291
2017-03-13T06:51:00.190
2808
33282
answer