9

CGLIBを介してプロキシされたクラスに属するメソッドのアノテーションをリフレクションで検索すると、奇妙な動作が発生します。SpringではCGLIBを使用しており、アノテーションのみでメソッドにアノテーションを付けるとうまく機能します(getAnnotations()対応するオブジェクトのメソッドを介してアノテーションを取得できMethodます)。代わりに(アノテーションの順序に関係なく)2つのアノテーションを使用してメソッドにアノテーションを付ける場合は、getAnnotations()を返しnullます。両方の注釈にはがありRetentionPolicy.RUNTIMEます。

CGLIBにはいくつかの問題があると読みましたが、1つの注釈に対してのみ機能し、2つの注釈を付けるとnullを返すのは奇妙です。

助言がありますか?

(Spring3.0.5およびCGLIB2.2.2を使用)

コードの追加:

最初の注釈は次のとおりです。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Produces {
    ResultType[] value();
}

2番目の注釈は

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface JamonMonitored {
    String type() default "";
    String tag() default "";
}

そして、コードのブロックは注釈をチェックするためのものです

Collection<Method> candidates = Collections2.filter(Arrays.asList(executorInstance.getClass().getMethods()), new Predicate<Method>() {
    @Override
    public boolean apply(Method input) {
        return input.getAnnotation(Produces.class) != null;
    }
});

if (candidates.isEmpty()) {
    // throws exception
}

@Producesと@JamonMonitoredの両方でメソッドにアノテーションを付けると、getAnnotation(Produces.class)は常にnullです。

4

2 に答える 2

18

CGLIB は、ターゲット オブジェクトのクラスのサブクラスを生成することによって機能し、そのサブクラスは、ターゲット オブジェクトにデリゲートするメソッドを生成しています。リフレクションを使用してプロキシ オブジェクトのアノテーションを照会する場合、ターゲット オブジェクトのクラスではなく、プロキシ クラスのアノテーションを要求しています。

Spring は、プロキシ、スーパークラス、インターフェースなどをナビゲートするために、多くの注釈処理を行う必要があります。これを行うためのロジックはカプセル化され、org.springframework.core.annotation.AnnotationUtilsクラスで公開されます。あなたの場合、ユーティリティメソッドが必要なようですfindAnnotation

@Override
public boolean apply(Method input) {
    return AnnotationUtils.findAnnotation(input, Produces.class) != null;
}
于 2012-01-25T16:00:18.883 に答える
2

別のオプションは、注釈定義内で @Inherited を指定することです。これにより、cglib によって生成されたサブクラスにも注釈が表示されます。もちろん、一部のシナリオでは、注釈を「実際の」サブクラスに表示したくないため、これはすべてのシナリオのオプションではない可能性があり、行く方法は、skaffman で示されているように Spring ヘルパーを使用することです

于 2013-01-18T10:58:47.993 に答える