Bibliotheken mittels Load-time weaving um Aspekte erweitern mit AspectJ 5

Thomas Darimont

Erfahrenes Mitglied
Hallo!

Hier mal ein kleines Beispiel wie man mit AspectJ 5 fremde Bibliotheken mit Aspekten ausstatten kann. Als Beispiel nehmen wir eine Klasse welche in einer Methode einen try...catch Block zur Ausnahmebehandlung enthält, diesen aber "ausversehen" leer gelassen hat... man soll es kaum glauben aber solcher Code gelangt auch heute noch in Produktionsumgebungen... :(.
Um diesem Dillema zu entfliehen verwenden wir AspectJ um die Ausnahmen die uns interessieren, aber von der eigentlichen Implementierung her nicht erscheinen doch noch anzuzeigen... ;-)

zum Laden unseres Aspekts verwenden wir eine Technik namens LoadTime-Weaving. Dies erlaubt es uns Klassen zum Ladezeitpunkt zu Instrumentieren (mit Aspekt-Code anzureichern). Dazu verwenden wir den von AspectJ 5 bereitgestellten javaagent aus aspectjweaver.jar. Dies funktioniert natürlich nur dann wenn die zugrundeliegende JVM Instrumentierung unterstützt. Das tun beispielsweise Java 5 via JVMTI (JVM Tool Interface) und BEAs JRockIt Implementierungen (dann auch schon für Java 1.3 und 1.4)

Im Folgendem definieren wir 2 Projekte. Projekt 1 ist ein ganz normales java Projekt in dem wir unsere "Geschäftslogik" implementieren. Projekt 2 besitzt eine Abhängigkeit zu Projekt 1 und beinhaltet die von uns definierten Aspekte.

Unser Beispiel: (Projekt 1)
Code:
/**
 * 
 */
package de.tutorials.business;

/**
 * @author Tom
 * 
 */
public class MainBusiness {

    /**
     * @param args
     */
    public static void main(String[] args) {
        System.out.println(makeMoney());
    }

    private static int makeMoney() {
        try {
            doAVeryBadThing();
            return 1000; // never reached but compiles ;-)
        } catch (Exception e) {
            // bad bad thing...
            // NEVER DO THIS
            return -1;
        }
    }

    /**
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static void doAVeryBadThing() throws Exception {
        throw new Exception("Attack a bank...");
    }
}
Das Projekt 1 exportieren wir nun in ein jar-File mit dem Namen business.jar

Unser ErrorHandlingAspect: (Projekt 2) gibt uns die Codestellen aus an der eine Exception aufgetreten ist und gibt den StackTrace aus.
Code:
package de.tutorials.aspects.errorhandling;

import de.tutorials.business.MainBusiness;
/**
 * @author Tom
 *
 */
public aspect ErrorHandlingAspect {
    pointcut businessMethodExecution() : execution(* MainBusiness.*(..));
        
    after() throwing (Exception e) : businessMethodExecution(){
        System.err.println("Exception occured after the execution of: " + thisJoinPoint.getSignature());
        e.printStackTrace();
    }
}
Zusätzlich zu unserem Aspekt definieren wir die Datei aop.xml welche wir im meta-inf Verzeichnis platzieren.

Unsere aop.xml im meta-inf Verzeichnis:
Code:
<aspectj>
          
   <aspects>
        <aspect name="de.tutorials.aspects.errorhandling.ErrorHandlingAspect"/>
   </aspects>

   <weaver options="-XlazyTjp">
        <include within="de.tutorials.business..*"/>
   </weaver>
          
</aspectj>
Das Projekt 2 exportieren wir nun in ein jar-File mit dem Namen debug-aspect.jar.

Einfacher Aufruf ohne Aspect:
Code:
C:\>java -jar business.jar
-1
Aufruf mit Aspect:
Zum Aufrufen des Aspekts benötigen wir verschiedene jars der AspectJ 5 Laufzeit:
-aspectjrt.jar
-aspectjweaver
-unser debug-aspect.jar

Ein Beispiel Aufruf könnte wie folgt aussehen
Code:
C:\>java -Daj.weaving.verbose=true -Dorg.aspectj.weaver.showWeaveInfo=true -javaagent:aspectjweaver.jar -Xbootclasspath/a:c:/debug-aspect.jar;c:/aspectjrt.jar -jar business.jar
info AspectJ Weaver Version 1.5.0 built on Tuesday Dec 20, 2005 at 13:26:12 GMT
info register classloader sun.misc.Launcher$AppClassLoader@24724388
info using file:/C:/debug-aspect.jar!/META-INF/aop.xml
info register aspect de.tutorials.aspects.errorhandling.ErrorHandlingAspect
info weaving 'de/tutorials/business/MainBusiness'
weaveinfo Join point 'method-execution(void de.tutorials.business.MainBusiness.doAVeryBadThing())' in Type 'de.tutorials.business.MainBusiness' (MainBusiness.java:35) advised by afterThrowing advice from 'de.tutorials.aspects.errorhandling.ErrorHandlingAspect' (ErrorHandlingAspect.aj:11)
Exception occured after the execution of: void de.tutorials.business.MainBusiness.doAVeryBadThing()
java.lang.Exception: Attack a bank...
        at de.tutorials.business.MainBusiness.doAVeryBadThing(MainBusiness.java:35)
        at de.tutorials.business.MainBusiness.makeMoney(MainBusiness.java:21)
        at de.tutorials.business.MainBusiness.main(MainBusiness.java:16)
-1

C:\>
Viel Spaß damit :) Btw. AspectJ rocks ;-)

Die beiden Jars findet man im Anhang.

Gruß Tom
 

Anhänge

  • aspectj5_example.zip
    5 KB · Aufrufe: 110
Zurück