2016-04-26 19 views
2

オブジェクトをOrientDBのVertexに変換するOGMを作成しようとしています。現在、私はGCLibを使用していますが、ByteBuddyは、動作すればOGMの速度を向上させるという2つの重要なことを実装できると読んでいます。ByteBuddy:フィールドアクセスインターセプタを実装する方法は?

  1. Could ByteBuddyはフィールドアクセス制御を実装していますか?私はその文書を読んだが、それは明らかではない、あるいは私はそれを理解していない。

  2. デフォルトの空のコンストラクタを動的に追加します。

現在の問題は次のとおりです。パラメータとして渡されるクラス定義はわかりません。アイデアは、クラスを再定義して空のコンストラクタを実装していない場合は実装し、割り当て操作が検出された場合はオブジェクトをダーティに設定するために__BB__Dirtyという名前のフィールドを追加し、インターフェイスの実装がオブジェクトと通信するように強制します。

例: ジェネリッククラス:

public class Example { 
    int i = 0; 
    String stringField; 

    public Example(Strinf s) { 
     stringField = s; 
    } 

    public void addToI(){ 
     i++; 
    } 
} 

今、私たちはこのようなインターフェイスている:だから

public interface DirtyCheck { 
    public boolean isDirty(); 
} 

、私は、インターフェイスを実装する方法のisDirtyを例クラスを強制したいです()、作業するフィールド、およびデフォルトのコンストラクタを使用してクラスを次のように変換する必要があります。

public class Example implements DirtyCheck { 
    int i = 0; 
    String stringField; 

    boolean __BB__dirty = false; 

    public Example() { 

    } 

    public Example(Strinf s) { 
     stringField = s; 
    } 

    public void addToI(){ 
     i++; 
    } 

    public boolean isDirty() { 
     return this.__BB__dirty; 
    } 
} 

といくつかの魔法のアサイナなので、__BB__dirtyを除くフィールドが変更された場合、__BB__dirtyフィールドはTrueに設定されます。

私はこれの最初の部分を試してみましたが、私は失敗:(

... 
ByteBuddyAgent.install(); 

Example ex = new ByteBuddy() 
       .redefine(Example.class) 
       .defineField("__BB__Dirty", boolean.class, Visibility.PUBLIC) 
       .make() 
       .load(Example.class.getClassLoader(), ClassReloadingStrategy.fromInstalledAgent()) 
       .getLoaded().newInstance(); 
.... 

ex.addToI(); // <--- this should set __BB__dirty to true since it 
       //  assign a value to i. 

しかし、私はこのエラーを取得:

Exception in thread "main" java.lang.UnsupportedOperationException: class redefinition failed: attempted to change the schema (add/remove fields) 
at sun.instrument.InstrumentationImpl.redefineClasses0(Native Method) 
at sun.instrument.InstrumentationImpl.redefineClasses(InstrumentationImpl.java:170) 
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy$Strategy$1.apply(ClassReloadingStrategy.java:297) 
at net.bytebuddy.dynamic.loading.ClassReloadingStrategy.load(ClassReloadingStrategy.java:173) 
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4350) 
at Test.TestBB.<init>(TestBB.java:33) 
at Test.TestBB.main(TestBB.java:23) 

I'amは、問題を解決するための非常に最初の段階で立ち往生BBを使用する ありがとう

答えて

0

Java仮想マシンは、クラスを再定義するときに既にロードされているクラスのレイアウトの変更をサポートしていません。これはBy VMの実装ではなく、バディです。

AgentBuilder APIをご覧ください。は、がロードされる前に変更することができます。エージェントを作成すると、しかし、クラスパスにライブラリを追加することに反対(起動時にエージェントとして明示的に追加する必要がない

あなたが呼び出すことによって、インターフェイスを実装することができます。

.implement(DirtyCheck.class).intercept(FieldAccessor.of("__dirty__"); 

あなたはまた、追加することができます単純に1を定義することで、デフォルトコンストラクタ:

.defineConstructor(Visibility.PUBLIC).intercept(SuperMethodCall.INSTANCE) 

後者の定義は、デフォルトコンストラクタを定義するには、スーパークラスが必要です

+0

答えをありがとう。javadocは現時点ではフィールドやメソッドの追加が許可されていないと言っていますが、この機能は将来のバージョンで追加される予定です。 私は別の方法を見つける必要があると思います。 私はGCLibでOGMを終了します。近い将来、私がBBで明確な方法で実装できるかどうかを確認するために戻ります。 –

+0

あなたは大歓迎です。 Byte Buddyは、より良い実行時パフォーマンスを提供するだけで、cglibで可能なことはすべてByte Buddyでも行うことができることに注意してください。 –

関連する問題