zoukankan      html  css  js  c++  java
  • [转载] Logging Standard Exceptions with Spring AOP

    Logging Standard Exceptions with Spring AOP

    Posted by Tejus Parikh on May 18, 2011

    One of the challenges of working on a large system with multiple developers is the management and handling of application errors and exceptions. Often, developers get frustrated with managing typed exceptions and all interfaces either throw or catch Exception. Another common approach is to change all exceptions to RuntimeException to avoid cluttering interfaces. An alternative approached is described in this paper by Andy Longshaw. His approach breaks exceptions into two distinct hierarchies, domain and system. Domain errors caused by logical faults in the application, such as a zero being passed as a divisor to a function. System errors are errors caused through the interaction with other components, like a network timeout when attempting to communicate with the database. Both exception types are checked exceptions, which means they must be caught and handled by each layer of the application. He presents guidelines on when and at which layer each type of exception should be logged. If you are using Java the obvious drawback of using checked exceptions everywhere is that each layer will be filled with code that looks like the following:

        try {
    
            service.doApiCall();
    
        } catch(DomainException e) {
    
            log.error("Domain exception occurred", e);
    
        } catch(SystemException e) {
    
            log.error("System exception occurred", e);
    
        }
    
    

    The duplication of handling of api exceptions can easily be handled with a custom annotation and Spring AOP. The first step is to create the Boundary logging annotation. This annotation describes where exceptions should be logged.

        @Retention(value = RetentionPolicy.RUNTIME)
    
        @Target(value = {ElementType.METHOD})
    
        public @interface BoundaryLogger {
    
        }
    
    

    Next, we need to create the interceptor. Along with just logging exceptions, I also choose to log the api calls. There are a few steps to creating an Aspect that can be used by Spring-AOP. First added the @Aspect annotation to the class declaration.

        @Service    // make this available as a spring bean
    
        @Aspect     // tell spring this class is an aspect
    
        public class BoundaryLoggingInterceptor {
    
    

    Next, create a method that tells the Aspect to do something before the underlying method, annotated with @BoundaryLogger, is called. In this example, it’s to log the method invocation.

        @Before("@annotation(net.vijedi.springlogging.interceptor.BoundaryLogger)")
    
        public void logInvocation(JoinPoint jp) {
    
    

    Similarly, triggering the aspect at method end can be handled with:

        @AfterReturning(
    
                pointcut = "@annotation(net.vijedi.springlogging.interceptor.BoundaryLogger)",
    
                returning = "retVal")
    
        public void logComplete(JoinPoint jp, Object retVal) {
    
    

    The one we are especially interested in for this purposes of this blog post is exception logging. This is the entire method for logging exceptions:

        @AfterThrowing(
    
                pointcut = "@annotation(net.vijedi.springlogging.interceptor.BoundaryLogger)",
    
                throwing = "ex"
    
        )
    
        public void processException(JoinPoint jp, Throwable ex) throws SystemException, DomainException {
    
            if(ex instanceof SystemException) {
    
                // System exceptions were logged at source
    
                // do not log the exception, just the return
    
                logReturn(jp, getLog(jp));
    
                throw (SystemException) ex;
    
            } else if(ex instanceof DomainException) {
    
                logException(jp, ex);
    
                throw (DomainException) ex;
    
            } else {
    
                logException(jp, ex);
    
                throw new DomainException(ex);
    
            }
    
    
    
        }
    
    

    The logException method is very simple:

        private void logException(JoinPoint jp, Throwable ex) {
    
            Log log = getLog(jp);
    
            log.error(ex.getMessage(), ex);
    
            logReturn(jp, log);
    
        }    
    
    

    How the logger is obtained is very important for accurate logging. Otherwise, it will appear that all logging messages are coming from the interceptor and not from the underlying method. Along with the confusion this could cause, it will also make it harder to use automatic log analyzers. However, it is very easy to get a logger in the context of the underlying class.

        protected Log getLog(JoinPoint jp) {
    
            return LogFactory.getLog(jp.getTarget().getClass());
    
        }
    
    

    Once the Aspect has been created, the final step is to tell spring what to do when it encounters the annotation @BoundaryLogger. There are four steps, tell spring to use annotations to configure the environment, to scan the packages the annotations are in, and to create the aop environment.

        

    This is all that’s need to use annotations for logging at the tier boundaries. The complete code for the example is available at my Spring Boundary Logging repo on Github.

    - See more at: http://www.tejusparikh.com/2011/logging-standard-exceptions-with-spring-.html#sthash.MNPx8RnM.dpuf

  • 相关阅读:
    自适应Simpson积分
    斜率优化
    ORM的单表增删改查
    MTV模型—urls和view
    迭代器与生成器
    s7day2学习记录
    s7day1学习记录
    AI车牌识别涉及哪些技术?它是如何改变行业的?
    技术分享:人脸识别究竟是如何完成的?
    TSINGEE青犀视频行人检测景区测试时视频流切换本地背景音乐无法播放问题优化
  • 原文地址:https://www.cnblogs.com/yuxiaoqi/p/4617882.html
Copyright © 2011-2022 走看看