Aspect | Eine Aufgabe die an verschiedenen Stellen im Programm benötigt wird, z.B. Logging. |
---|---|
Jointpoint | Wohldefinierter Punkt im Programmfluss an dem der Aspekt eingreift. Dies sind zum Beispiel Methodenaufrufe, Feldzugriffe oder Exceptions. In Spring sind nur Methodenaufrufe als Joinpoints möglich. |
Advice | Aktion eines Aspekts am Joinpoint, also der Code der am Joinpoint ausgeführt wird. Hier würde z.B. das Loggen ausgeführt. |
Pointcut | Muster, das die für den Aspekt wichtigen Joinpoints zusammenfasst. |
before | Advice wird vor der Methode ausgeführt. |
---|---|
after returning | Wird ausgeführt wenn die Methode normal (ohne Exception) beendet. |
after throwing | Wird ausgeführt wenn die Methode mit dem Werfen einer Exception beendet. |
after finally | Wird nach Beendigung der Methode ausgeführt, egal ob normal oder mit Exception. |
around | Wird vor und nach der Methode ausgeführt. Es gibt die Möglichkeit auf das Ergebnis der Methode zu reagieren. |
Ohne AOP (kein Proxy): der Aufruf wird direkt auf dem Objekt ausgeführt.
Mit AOP (mit Proxy): In diesem Fall ein before-Advice. Der Aufruf wird von dem Proxy abgefangen, der Advice ausgeführt und danach die original-Methode des Objekts aufgerufen.
Das Versehen eines Objekts mit einem Proxy heisst Weaving und wird von Spring zur Laufzeit ausgeführt. Dieses Vorgehen ist bei final Klassen nicht möglich, da der Proxy die Klasse in den per Advice zu erreichenden Methoden erweitert. Spring bietet drei Möglichkeiten Aspektorientierung zu implementieren, die im folgenden vorgestellt werden.<aop:aspectj-autoproxy/>
einzuführen. Der Aspekt selbst wird ebenfalls als Bean bekanntgemacht:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <aop:aspectj-autoproxy/> <bean id="loggingAspect" class="Logging"> <!-- ggf. properties / constructor-args --> </bean> <!-- andere Beans --> </beans>Die Änderungen im Header machen den AOP-Namespace bekannt, damit <aop:aspectj-autoproxy/> verstanden wird. In der Klasse Logging ist der Aspekt mit Pointcuts und Advices definiert:
import org.aspectj.lang.annotations.Aspect; import org.aspectj.lang.annotations.Pointcut; import org.aspectj.lang.annotations.Before; import org.aspectj.lang.annotations.Around; import org.aspectj.lang.ProceedingJoinPoint; @Aspect public class Logging { @Pointcut("execution(* myTask.do(..))") public void doWork() {} @Before("doWork()") public void doLogging() { //Aktionen vor der myTask.do()-Methode } @Before("execution(* myTask.do(..))") public void doLoggingToo() { //Gleichwertig mit dem Before(doWork())-Advice } @Around("doWork()") public Object doLoggingAround(ProceedingJoinPoint pjp) { //Aktionen vor der Ausführung von myTask.do() Object retVal = pjp.proceed(); //myTask.do() ausführen //Aktionen nach der Ausführung von myTask.do() return retval; } }In der Klasse gibt @Aspect an, dass es sich bei dieser Klasse um einen Aspekt handelt. @Pointcut gibt ein Muster für die Stellen an, an denen sich darauf beziehenden Advices ausgeführt werden. Die Muster des Pointcuts lassen dabei Verknüpfungen wie
||
(oder) oder &&
(und) zu. Die Syntax der Pointcuts bei @AspectJ in Spring und AOP mit
XML-Schema lässt Wildcards zu. So bedeutet "(* myTask.do(..))"
, dass der Pointcut für die Methode do
aus der Klasse myTask
unabhängig von den angegebenen Parametern gilt. Der erste @Before-Advice bezieht sich auf
diesen Pointcut und die Methode doLogging
wird vor der Methode do
ausgeführt. Der zweite
@Before-Advice erzeugt sich seinen eigenen Pointcut. Dies ist sinnvoll wenn an diesem Pointcut nur ein Advice ausgeführt
werden soll. Der @Around-Advice zeigt wie die Aktionen vor- und hinter der do
-Methode ausgeführt werden.
||
oder &&
zu verknüpfen. Der Header der XML-Datei entspricht dabei dem der Benutzung der @AspectJ-Syntax. Eine mit dem obigen
Beispiel gleichwertige Konfiguration würde folgendermaßen aussehen:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> <bean id="loggingAspect" class="Logging"> <!-- ggf. properties / constructor-args --> </bean> <aop:config> <aop:aspect ref="loggingAspect"> <aop:pointcut id="doWork" expression="execution(* myTask.do(..))"/> <aop:before pointcut-ref="doWork" method="doLogging"/> <aop:before pointcut="execution(* myTask.do(..))" method="doLoggingToo"/> <aop:around pointcut-ref="doWork" method="doLoggingAround"/> </aop:aspect> </aop:config> <!-- andere Beans --> </beans>Das
<aop:config>
-Tag leitet die Konfiguration ein. In diesem Tag können mehrere Aspekte konfiguriert
werden. Es ist auch möglich Pointcuts direkt unter diesem Tag zu konfigurieren, wodurch sie in allen Aspekten genutzt werden
können. Die Konfiguration von Pointcuts erfolgt im <aop:pointcut>
-Tag mit einer id
zum
referenzieren und einer expression
, die das Muster vorgibt an welchen Stellen ein Advice ausgeführt werden soll.
Die Tags für die unterschiedlichen Adivces lauten <aop:before>
, <aop:after-returning>
,
<aop:after-throwing>
, <aop:after-finally>
sowie <aop:around>
.
Die Attribute sind für alle Advices pointcut-ref
oder pointcut
, wodurch Pointcuts referenziert oder
angegeben werden, sowie method
, wo die auszuführende Methode angegeben wird.