Blog

Mehr Groovy-Power

Lars Vonk

Aktualisiert Oktober 23, 2025
4 Minuten

Nach meiner ersten richtigen Begegnung mit Groovy war ich wirklich begeistert und beschloss, einige meiner persönlichen Trainingstage dafür zu verwenden, mehr Erfahrung mit Groovy zu sammeln. Als Studienmaterial habe ich das Buch Programming Groovy gelesen. Während des Lesens wollte ich mir wirklich die Hände schmutzig machen, also beschloss ich, als Studienfall eine meiner längsten und größten Frustrationen als Entwickler zu lösen, nämlich die Arbeit hinter einem Proxy-Server. Die Idee, die ich hatte, war, ein Groovy-Programm zu erstellen, das es ermöglicht, die Proxy-Einstellungen für Anwendungen wie (Maven, Subversion, Internet Explorer, Firefox und so weiter) mit einem einzigen Befehl ein- oder auszuschalten: groovy com/xebia/proxy/SwitchProxy on/off. Hier finden Sie eine kurze Zusammenfassung einiger der Techniken, die ich bei der Erstellung dieses Programms verwendet habe.

Dynamischer Aufruf von Methoden Da Groovy dynamisch ist, habe ich mich entschieden, keine Schnittstellen zu verwenden, denn wozu braucht man in einer dynamischen Sprache überhaupt Schnittstellen? Jede Klasse, die eine Anwendung repräsentiert, für die ein Proxy umgeschaltet werden muss, muss lediglich eine Methode mit den Namen "on" und "off" haben. In Groovy können Sie einen String als Methodennamen verwenden. Da "on" und "off" in der Hauptmethode von SwitchProxy als String übergeben werden, sollten Sie dies als Namen der Methode verwenden. Hier ist die Kurzversion von SwitchProxy:

static void main(String[] args) { def operation = args[0] proxySwitcher."$operation"(); }

Dadurch wird die Methode aufgerufen, die den gleichen Namen wie der übergebene Parameter hat, in unserem Fall "on" oder "off". So einfach, dass es fast nicht erwähnenswert ist... Instanziierung von Groovy-Klassen zur Laufzeit Das Skript, das ich geschrieben habe, liest die zu proxyenden Anwendungen aus einer Konfigurationsdatei. Da ich möchte, dass mein Skript nur über den Groovy-Befehl läuft und nur Groovy-Dateien verwendet, musste ich eine Möglichkeit finden, eine Groovy-Klasse über ihren Namen zu instanziieren. Aus der Sicht eines Programmierers möchte ich in der Lage sein zu sagen: "com.xebia.proxy.ie.InternetExplorer".newInstance(). Sie können die MetaClass-Funktionen von Groovy nutzen, um eine neue Methode für String einzuführen:

String.metaClass.newInstance = { //implementation here. }

Mein erster Gedanke war, dafür das gute alte Class.forName zu verwenden, aber das sucht natürlich nach kompilierten Java-Klassen, die es in meinem Fall nicht gibt. Ich hätte beschließen können, meinen Code einfach zu kompilieren und damit fertig zu sein... aber wo bleibt der Spaß dabei? Die Lösung, die ich gefunden habe, besteht darin, die Klassen, die ich instanziieren muss, zur Laufzeit zu kompilieren. Dies schien in Groovy sehr einfach zu sein (was es übrigens nicht ist...):

String.metaClass.newInstance = {
  def clazz
  try {
    //will fail the first time.
    clazz = Class.forName(delegate)
  } catch(ClassNotFoundException e) {
    def compiler = new Compiler()
    def groovyFile = delegate.replaceAll("\.", "/") + ".groovy"
    compiler.compile(new File(groovyFile))
    // now try again...
    clazz = Class.forName(delegate)
  }
  return clazz.newInstance()
}

Das Schlüsselwort delegate bezieht sich in diesem Fall auf das String-Objekt selbst.

Kategorien Neben der Verwendung von Groovy-MetaClass-Funktionen für die Injektion von Methoden, wie oben gezeigt, können Sie auch Kategorien verwenden. Kategorien sind Klassen, die es Ihnen ermöglichen, eine bestimmte Klasse innerhalb eines bestimmten Bereichs zu erweitern. Ich fand diese Technik beim Testen sehr praktisch. Hier ist ein vereinfachtes Beispiel: Ich wollte testen, dass eine Meldung auf der Konsole ausgegeben wird, wenn ein Benutzer vergisst, entweder "on" oder "off" einzugeben. Um dies mit Kategorien zu erreichen, definieren Sie zunächst Ihre Kategorie:

class MockPrinter { static def printedText def static println(self, text) {printedText = text} }

Damit wird die println-Methode von Groovy in einem bestimmten Bereich über das Schlüsselwort use außer Kraft gesetzt und der zu druckende Text auf die Eigenschaft printedText gesetzt. Um also die Kategorie in Ihrem Test zu verwenden:

void testShouldFailWhenNoParametersArePassedIn() { use(MockPrinter) { SwitchProxy.main() } assertEquals(SwitchProxy.USAGE, MockPrinter.printedText) }

Das war's fürs Erste. Wenn Sie möchten, können Sie sich den vollständigen Quellcode des Proxy-Skripts os.xebia.com/svn/mojo/proxy-switcher/tags/1.0/ ansehen. Der Code ist natürlich selbstdokumentierend :-). Lars

Verfasst von

Lars Vonk

Contact

Let’s discuss how we can support your journey.