2011-03-15 28 views
5

Chúng tôi đang sử dụng Spring với slf4j và hibernate, tôi đang cố gắng tìm ra cách để ghi lại các ngoại lệ và các lỗi một cách tự động (nghĩa là không khởi tạo một trình gỡ lỗi trong mỗi lớp). và cũng có thể có được lớp học và phương pháp tên trong nhật ký,Spring - slf4J: cách tự động ghi lại các lỗi và ngoại lệ?

tôi đọc một lưu ý rất ngắn về việc sử dụng các khía cạnh & chặn cho điều này, vì vậy bạn có thể cung cấp cho tôi với một số cách chi tiết để thực hiện điều này,

Kính trọng,

+0

Điều này sẽ đạt được điều gì mà bạn chưa có từ dấu vết ngăn xếp? Nếu bạn có kế hoạch đăng nhập và nuốt các ngoại lệ thông qua các khía cạnh, mà âm thanh như một ý tưởng khá xấu với tôi. –

Trả lời

10

một khía cạnh ngoại lệ có thể trông giống như sau:

conf
@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; 
    } 
    } 
} 

mùa xuân:

<!-- 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:

nếu bạn muốn logger để đăng nhập trên danh nghĩa của đậu bọc, bạn có thể tất nhiên làm:

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

hoặc nếu bạn đặt trước lớp khai báo của phương thức này chứ không phải loại thực tế (có khả năng được tạo sẵn/được tạo tự động):

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

Thành thật mà nói, tôi không thể ước tính hiệu quả của việc gọi LoggerFactory.getLogger (..) mỗi lần. Tôi cho rằng nó không quá tệ, vì ngoại lệ là ngoại lệ (ví dụ hiếm).

+0

Câu trả lời của bạn là cực kỳ rõ ràng, nhưng nếu tôi muốn logger đăng nhập với tên lớp gọi, không phải tên lớp khía cạnh của tôi? –

+0

@Amr xem "EDIT:" – sfussenegger

+0

Câu trả lời của bạn ngày càng trở nên tốt hơn và tốt hơn, bạn cũng đã đề cập đến vấn đề về hiệu suất, cũng đang nghĩ đến, Cảm ơn bạn rất nhiều –

0

Với Aspect J tinh khiết (bạn cũng có thể sử dụng nó cho các bean không được quản lý mùa xuân). Ví dụ này ghi lại tất cả các ngoại lệ "được trả về" bởi một phương thức dịch vụ. Nhưng bạn có thể thay đổi các điểm cắt mà nó phù hợp với các phương pháp khác quá.

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);   
    } 
} 

Nó được viết cho JUnit, nhưng bạn có thể dễ dàng điều chỉnh nó.

Các vấn đề liên quan