3

次のテスト ケースでは、直接フィールド t は CGLIB によってインターセプトされません。それで、CGLIBを使用できますか?

public class Test {

@Test
public void testCGLib() {
    A a = (A) Enhancer.create(A.class, new Class[] {}, new B());
    System.out.println(a.t);
    a.t();
}

public static class A {

    public int t = 0;

    public void t() {
        System.out.println("bbb");
    }

}

public static class B implements LazyLoader {

    @Override
    public Object loadObject() throws Exception {
        System.out.println("xxx");
        return new A();
    }
}
}
4

1 に答える 1

2

いいえ、それはできません。フィールド アクセスは、フィールドを定義するクラスの一部のバイト コードに委譲されません。フィールドを使用するメソッドによって直接ロードされます。(あなたの場合、これはTest#testCGLibです。)

cglib はサブクラスを作成し、メソッド呼び出しをインターセプトします。ただし、フィールドは上書きできず、cglib の有無にかかわらず、多態的ではありません。したがって、フィールド アクセスをインターセプトすることはできません。サブクラスのフィールドのみを非表示にできます。

ただし、インストルメント化されたクラスでフィールドを隠していたとしてもA#t、cglib クラスはコンパイル時に表示されないため、インストルメント化された型でフィールドを参照することはできません。インストルメント化されたクラスA$$cglibにフィールドがあった場合、次のt方法でのみアクセスできます

a.getClass().getField("x").get(a)

ある種の動的フィールドバインディングをエミュレートするため。(基本的に、メソッドは動的にバインドされ、その結果、正しいフィールドが動的に選択されます。

于 2013-11-13T23:00:01.790 に答える