English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
この二日間、Hibernateのアーティファクト部分を見て、まず思ったのは、ベースレベルで反射を使用していることでした。ユーザーエンティティに対してアーティファクトクラスが生成されています。その後、反射は新しいクラスを生成する能力がありませんと気づき、自然とJavassist(ダウンロードリンク)にたどり着きました。
オンラインで検索した多くのチュートリアルは、JavassistのAPIについて説明していますが、最終的には、通常、ロードプロセスがありません。筆者がこれらのチュートリアルを模倣してクラスをロードすると、元のクラスが読み込まれ、バイトコードが変更された内容が生成されませんでした。
一連の探索の後、筆者は、オンラインの多くのチュートリアルの最後の手順、バイトコードの保存には、writeFileの無引数のオーバーロードを使用していることに気づきました。その関数の構造を確認すると、String型のオーバーロードもありました。Eclipseでは、バイトコードの保存先のルートは「.\\」ではなく「.\\bin」となり、writeFileの別のオーバーロードはおそらくバイトコードのルート位置を指定するパラメータであると考えられました。筆者が変更を加えると、果たしてその通りでした。
以下にコードを共有します:
これは筆者のプロジェクトの構造です:
Editable.java: package com.thrblock.javassist; public class Editable {}} public void showInfo(){ System.out.println("InfoDefault!"); } }
Main.java: package com.thrblock.javassist; import java.io.IOException; import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; import javassist.CtMethod; import javassist.CtNewMethod; import javassist.NotFoundException; public class Main { public static void main(String[] args) { ClassPool pool = ClassPool.getDefault(); try{}} pool.insertClassPath(".\\bin"); //ルートパスを設定します。(ここで設定されたルートパスはwriteFileで使用されていません) CtClass cc = pool.makeClass("com.thrblock.javassist.EditableChanged"); //Hibernateの代理モードをシミュレートするために、新しいクラスを作成します cc.setSuperclass(pool.get("com.thrblock.javassist.Editable")); //その親クラスを設定します CtMethod cm = CtNewMethod.make("public void showInfo(){super.showInfo();System.out.println("CustomInsertHAHA!");}",cc); //メソッドを追加しますが、注意して父クラスのメソッドをオーバーライドしています。 cc.addMethod(cm); cc.writeFile(".\\bin"); //ここは非常に重要であり、空の引数の結果はeclipseのバイトコードのルートパスに保存されていません。 } catch (NotFoundException | CannotCompileException | IOException e) { e.printStackTrace(); } try{}} Class<?> cl = Class.forName("com.thrblock.javassist.EditableChanged"); //新しいクラスをロードします Editableed = (Editable) cl.newInstance(); //Editableクラスを継承しているため、ここはHibernateのloadと同じ原理です。 ed.showInfo(); //メソッドを呼び出します。 } catch (ClassNotFoundException | InstantiationException |IllegalAccessException e) { e.printStackTrace(); } } }
出力結果:
InfoDefault!
CustomInsertHAHA!
他の注意点:
我々が生成したクラスが元のクラス名と同じであれば、classファイルを上書きしますが、そのclassがJVMにすでに読み込まれていた場合、変更された部分は有効ではなく、JVMを再起動する必要があります。
まとめ
これで、Eclipse下でのJavassistの正しい使用方法に関するコード解析の全てが終わりました。皆様にお役立ていただけますように。興味を持たれた方、他の関連する特集もご覧ください。不十分な点があれば、コメントをお待ちしております。皆様のサポートに感謝します。
声明:本文の内容はインターネットからネットワークで提供されています。著作権は原著者に帰属します。インターネットユーザーが自発的に貢献し、アップロードしたものであり、本サイトは所有権を持ちません。また、人工的な編集は行われていません。著作権侵害を疑う内容があれば、メールで notice#w までご連絡ください。3codebox.com(メール送信時は、#を@に変更してください。報告を行い、関連する証拠を提供してください。一旦確認が取れましたら、本サイトは即座に侵害を疑われる内容を削除します。)