Communardo Software GmbH, Kleiststraße 10 a, D-01129 Dresden

Logging per Interceptor mit Spring

Wenn man in Spring-Anwendungen zum Beispiel den Aufruf von Methoden log­gen will, aber nicht in jeder gewünsch­ten Methode eine Log-Anweisung ein­fü­gen möchte, kann man das Logging zen­tral als Aspekt defi­nie­ren. Es kön­nen damit die Methodenaufrufe aller Klassen geloggt wer­den, die als Bean durch Spring ver­wal­tet werden.

Zu Beginn sollte die Bean für den Interceptor (advice) defi­niert werden.

<bean id="methodLoggingInterceptor" class="MethodLoggingInterceptor"/>

Danach kann eine advi­sor ver­wen­det wer­den, der auf den Interceptor (advice) ver­weist und die join­points (die gewüsch­ten Methoden) über einen regu­lä­ren Ausdruck engrenzt.

<bean id="wsMethodLogger" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
     <property name="advice">
          <ref local="methodLoggingInterceptor"/>
     </property>
     <property name="patterns">
          <list>
               <value>de.communardo.*get.*</value>
               <value>de.communardo.*process.*</value>
          </list>
     </property>
</bean>

Dann muss den betref­fen­den Beans der neue Interceptor hin­zu­ge­fügt wer­den. Hierbei ist auf die Reihenfolge zu achten.

<bean id="profileWebservice">
    ...
    <property name="interceptorNames">
         <list>
              <value>serviceTransactionInterceptor</value>
              <value>hibernateInterceptor</value>
              <value>wsMethodLogger</value>
         </list>
    </property>
</bean>

Die Interceptor-Klasse kann zum Beispiel die Interfaces MethodBeforeAdvice, AfterReturningAdvice und ThrowsAdvice imple­men­tie­ren. In den ent­spre­chen­den Methoden kann dann je nach Aufrufzeitpunkt eine geeig­nete Meldung ins Log geschrie­ben werden.

import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;

public class MethodLoggingInterceptor implements MethodBeforeAdvice, AfterReturningAdvice,
ThrowsAdvice {
    private Logger log = null;
    public MethodLoggingInterceptor() {
    }
    public void before(Method method, Object[] args, Object object) throws Throwable {
        log = Logger.getLogger(object.getClass());
        log.debug("Beginning method: " + method.getName());
    }
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target)
    throws Throwable {
        log = Logger.getLogger(target.getClass());
        log.debug("Ending method: " + method.getName());
    }
    public void afterThrowing(Method method, Object[] args, Object target, Throwable ex) {
        log = Logger.getLogger(target.getClass());
        log.debug("Exception in method: " + method.getName() + " Exception is: " + ex.getMessage());
    }
}

Hinweis für AndroMDA-Nutzer: Für Klassen, die über den Stereotyp <<Service>> ver­fü­gen, exis­tiert der tag­ged value @andromda.spring.service.interceptors. Darüber las­sen sich den Services im Modell zusätz­li­che Interceptors hin­zu­fü­gen, die in die Liste der interceptorNames auf­ge­nom­men wer­den. Die Spring-Konfiguration der betei­lig­ten Beans kann anhand des applicationContext merge-point in den Application Context inte­griert werden.

21. Juli 2008

Pin It on Pinterest