English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

EclipseでJavassistを正しく使用する方法のコード解析

この二日間、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(メール送信時は、#を@に変更してください。報告を行い、関連する証拠を提供してください。一旦確認が取れましたら、本サイトは即座に侵害を疑われる内容を削除します。)

おすすめ