© Excellent backgrounds/Shutterstock.com
Code statt dynamischer Proxies generieren

Es werde Code!


Warum nicht einen Proxy so generieren, wie man ihn benötigt? Aber wie fängt man an und was sollte beachtet werden? Es ist leichter, als man vermuten könnte.

Im JDK gibt es das Compiler-API. Dieses ermöglicht dem Entwickler, zur Laufzeit Java-Klassen selbst zu übersetzen. Eines der Haupteinsatzgebiete ist die Verwendung im Zusammenhang mit Codegeneratoren, die Java-Quelltexte erzeugen. Nach dem Übersetzungsvorgang kann man das Ergebnis über einen Class Loader direkt laden und verwenden. Prinzipiell gibt es verschiedene Vorgehensweisen. Wir werden uns hier den standardisierten Java-Compiler aus dem Package javax.tools ansehen. Dieser ist seit Java 6 im JDK enthalten und wurde erstmals im JSR-199 „Java Compiler API“ definiert. Um zur Laufzeit dynamisch Bytecode zu erzeugen, ist für uns die Möglichkeit von Interesse, aus einem String heraus Bytecode zu erzeugen und zu laden. Der String soll zur Laufzeit generiert und nicht aus einer Datei geladen werden.

Prinzipiell werden folgende Teile benötigt: Zum einen eine Klasse, die den Quellcode repräsentiert, in unserem Fall GeneratedJavaSourceFile. Zu beachten ist an dieser Stelle, dass die Repräsentation final in einer CharSequence vorliegen muss. Der Aufbau selbst ist recht simpel. Es wird ein URI angegeben, der hier lediglich aus einem Klassennamen mit der Sourcecode-Extension (Java) besteht, und der Typ Kind.SOURCE. Der Inhalt selbst wird in einem Attribut vom Typ CharSequence mit dem Namen javaSource gespeichert (Listing 1).

Listing 1

public class GeneratedJavaSourceFile extends SimpleJavaFileObject { private CharSequence javaSource; public GeneratedJavaSourceFile(String className, CharSequence javaSource) { super(URI.create(className + ".java"), Kind.SOURCE); this.javaSource = javaSource; } public CharSequence getCharContent( boolean ignoreEncodeErrors) throws IOException { return javaSource; } }

Das Gegenstück zum Quelltext ist der Bytecode. Dieser wird durch die Klasse GeneratedClassFile wiedergegeben. Der Aufbau ist ähnlich wie der von der Sourcecode-Repräsentation. Der URI enthält den Klassennamen mit der Extension class, und der übergebene Typ ist nun Kind.CLASS. Die generierte Klasse selbst wird im Attribut outputStream vom Typ ByteArrayOut­put­Stream gespeichert (Listing 2).

Listing 2

public class GeneratedClassFile extends SimpleJavaFileObject { private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); public GeneratedClassFile() { super(URI.create("generated.class"), JavaFile...

Exklusives Abo-Special

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang