Spring - slf4J: как автоматически регистрировать ошибки и исключения? - PullRequest
5 голосов
/ 15 марта 2011

Мы используем Spring с slf4j и hibernate, я пытаюсь найти способ автоматически регистрировать исключения и ошибки (т.е. без инициализации экземпляра отладчика в каждом классе), чтобы он мог перехватить любую ошибку или исключениеа также получить имя класса и метода в журнале,

Я прочитал очень короткую заметку об использовании аспектов и перехватчиков для этого, поэтому не могли бы вы предоставить мне какой-то подробный способ реализации этого,

С уважением,

Ответы [ 2 ]

10 голосов
/ 15 марта 2011

аспект исключения может выглядеть следующим образом:

@Aspect
public class ExceptionAspect {

  private static final Logger log = LoggerFactory.getLogger(ExceptionAspect.class);

  public Object handle(ProceedingJoinPoint pjp) throws Throwable {
     try {
       return pjp.proceed();
     } catch (Throwable t) {
       // so something with t: log, wrap, return default, ...
       log.warn("invocation of " + pjp.getSignature().toLongString() + " failed", t);
       // I hate logging and re-raising, but let's do it for the sake of this example
       throw t;
     }
  }
}

весенний конф:

<!-- log exceptions for any method call to any object in a package called 'svc' -->
<bean class="org.example.aspects.ExceptionAspect" name="exceptionAspect" />
<aop:config>
  <aop:aspect ref="exceptionAspect">
    <aop:around method="handle" pointcut="execution(* org.example..svc..*.*(..))" />
  </aop:aspect>
</aop:config>

EDIT:

если вы хотите, чтобы регистратор входил в систему от имени упакованного компонента, вы, конечно, можете сделать:

LoggerFactory.getLogger(pjp.getTarget().getClass()).warn("damn!");

или если вы предпочитаете декларирующий класс этого метода, а не фактический (потенциально прокси / автоматически сгенерированный тип):

LoggerFactory.getLogger(pjp.getSignature().getDeclaringType()).warn("damn!");

Честно говоря, я не могу оценить последствия для производительности при вызове LoggerFactory.getLogger (..) каждый раз. Я предположил бы, что это не должно быть слишком плохо, поскольку исключения являются исключительными (то есть редкими) в любом случае.

0 голосов
/ 15 марта 2011

С чистым Aspect J (чем вы можете использовать его и для неуправляемых бобов).Этот пример регистрирует все исключения, «возвращенные» методом службы.Но вы можете изменить pointcut, чтобы он соответствовал и другим методам.

package test.infrastructure.exception;

import java.util.Arrays;

import org.apache.log4j.*;
import org.aspectj.lang.Signature;
import org.springframework.stereotype.Service;

/** Exception logger*/
public aspect AspectJExceptionLoggerAspect {

    /** The name of the used logger. */
    public final static String LOGGER_NAME = "test.infrastructure.exception.EXCEPTION_LOGGER";

    /** Logger used to log messages. */
    private static final Logger LOGGER = Logger.getLogger(LOGGER_NAME);

    AspectJExceptionLoggerAspect() {
    }

    /**
     * Pointcut for all service methods.
     * 
     * Service methods are determined by two constraints:
     * <ul>
     *   <li>they are public</li>
     *   <li>the are located in a class of name *SericeImpl within (implement an interface)
     *   {@link test.service} package</li>
     *   <li>they are located within a class with an {@link Service} annotation</li>
     * </ul>
     */
    pointcut serviceFunction()
        : (execution(public * test.Service.*.*ServiceImpl.*(..)))  
        && (within(@Service *));

    /** Log exceptions thrown from service functions. */
    after() throwing(Throwable ex) : serviceFunction() {
        Signature sig = thisJoinPointStaticPart.getSignature();
        Object[] args = thisJoinPoint.getArgs();

        String location = sig.getDeclaringTypeName() + '.' + sig.getName() + ", args=" + Arrays.toString(args);
        LOGGER.warn("exception within " + location, ex);        
    }
}

Он написан для JUnit, но вы можете легко адаптировать его.

...