Verwenden einer Metaprogrammierbibliothek namens javassist Ich habe versucht, die Klasse, die ich tatsächlich erstellt habe, neu zu schreiben.
Sie können es verwenden, wenn Sie die Bibliothek verwenden und denken, es ist Scheiße. (Es wird ein mysteriöses Protokoll ausgegeben usw.)
Ich benutze Gradle.
build.gradle
...
dependencies {
...
compile group: 'org.javassist', name: 'javassist', version: '3.15.0-GA'
}
Schreiben Sie die vorbereitete Klasse namens User tatsächlich neu. Fügen Sie ein Feld namens Geld hinzu.
data/User.java
package data;
public class User {
private String name;
private int age;
private float height;
private float width;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String getUserInfo() {
return "name: " + name + ", age: " + age;
}
}
Main.java
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.Modifier;
public class Test {
public static void main(String[] args) {
try {
//Holen Sie sich Pools für alle Klassen.
ClassPool pool = ClassPool.getDefault();
//Vollständige Daten des Paketnamens und des Klassennamens.Suche nach Benutzer
//Wenn nicht gefunden, wird eine Ausnahme ausgelöst.
CtClass ctc = pool.get("data.User");
//Geben Sie in den Argumenten den Feldtyp, den Feldnamen und das Deklarationsziel an.
CtField field = new CtField(CtClass.intType, "money", ctc);
//Geben Sie den Feldmodifikator an
//Wenn es mehrere Modifikatoren gibt|Ich werde es mit hinzufügen.
// field.setModifiers(Modifier.STATIC | Modifier.PRIVATE);
field.setModifiers(Modifier.PRIVATE);
//Feld hinzufügen.
ctc.addField(field);
//Holen Sie sich die definierte Methode.
CtMethod method = ctc.getDeclaredMethod("getUserInfo");
//Geändert, um Geld auszugeben, indem das Innere der Methode ersetzt wird.
method.setBody("return \"name: \" + name + \", age: \" + age + \", money: \" + money;");
//Klasse im Klassenlader überschreiben.
Class cls = ctc.toClass(ClassLoader.getSystemClassLoader(), AsmTest.class.getProtectionDomain());
//Erstellen Sie eine Instanz einer Klasse mit Reflektion.
User ins = (User) cls.newInstance();
ins.setName("Bob");//Geben Sie Bob als Namen an.
//Da Geld nach der Zusammenstellung hinzugefügt wird, erhalten Sie es durch Reflexion.
Field f = cls.getDeclaredField("money");
//Zugänglichkeit geändert.
//Wenn privat oder geschützt, setzen Sie es auf true, damit auf es zugegriffen werden kann.
f.setAccessible(true);
//Ändern Sie das Geldfeld mit int auf 1500.
f.setInt(ins, 1500);
//Tatsächliche Ausgabe.
System.out.println("name: " + ins.getName());
System.out.println("money: " + f.getInt(ins));
System.out.println(ins.getUserInfo());
} catch (Exception e) {
//Fehler ausgeben.
System.out.println(e);
}
}
}
Ergebnis ist ...
name: Bob
money: 1500
name: Bob, age: 0, money: 1500
Wie, das Feld namens Geld wächst, Sie können den Wert ändern.
Ich habe nur das Hinzufügen dieses Feldes eingeführt, aber da gibt es verschiedene andere Funktionen Bitte benutzen Sie es auf jeden Fall.
javassist https://github.com/jboss-javassist/javassist
Recommended Posts