Метод мониторинга с помощью Spring Aspect - PullRequest
2 голосов
/ 23 мая 2019

Я хочу реализовать Spring Aspect для ведения журнала. Я попробовал эту реализацию:

Аспект для ведения журнала:

    import org.apache.commons.lang.builder.ReflectionToStringBuilder;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.stereotype.Component;
    import javax.servlet.http.HttpServletRequest;
    import java.util.Arrays;
    import java.util.Enumeration;

    @Aspect
    @Component
    public class LoggingAspect {

        private static final String CONTROLLER_EXPRESION = "within(@org.springframework.stereotype.Controller *) && execution(* *.*(..))";
        private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);

        /**
         * Before -> Any resource annotated with @Controller annotation and all method
         * and function taking HttpServletRequest as first parameter.
         *
         * @param joinPoint
         * @param request
         */
        @Before(CONTROLLER_EXPRESION)
        public void logBefore(JoinPoint joinPoint, HttpServletRequest request) {

            log.debug("Entering in Method : {}", joinPoint.getSignature().getName());
            log.debug("Class Name :  {}", joinPoint.getSignature().getDeclaringTypeName());
            log.debug("Arguments :  {}", Arrays.toString(joinPoint.getArgs()));
            log.debug("Target class : {}", joinPoint.getTarget().getClass().getName());

            if (null != request) {
                log.debug("Start Header Section of request ");
                log.debug("Method Type : {}", request.getMethod());
                Enumeration headerNames = request.getHeaderNames();
                while (headerNames.hasMoreElements()) {
                    String headerName = headerNames.nextElement().toString();
                    String headerValue = request.getHeader(headerName);
                    log.debug("Header Name: {} Header Value : {}", headerName, headerValue);
                }
                log.debug("Request Path info : {}", request.getServletPath());
                log.debug("End Header Section of request ");
            }
        }

        /**
         * After -> All method within resource annotated with @Controller annotation.
         *
         * @param joinPoint
         * @param result
         */
        @AfterReturning(pointcut = CONTROLLER_EXPRESION, returning = "result")
        public void logAfter(JoinPoint joinPoint, Object result) {
            String returnValue = this.getValue(result);
            log.debug("Method Return value : {}", returnValue);
        }

        /**
         * After -> Any method within resource annotated with @Controller annotation and throws an exception ...Log it 
         * @param joinPoint
         * @param exception
         */
        @AfterThrowing(pointcut = CONTROLLER_EXPRESION, throwing = "exception")
        public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {
            log.error("An exception has been thrown in {} {}", joinPoint.getSignature().getName(), " ()");
            log.error("Cause : {}", exception.getCause());
        }

        /**
         * Around -> Any method within resource annotated with @Controller annotation. 
         * @param joinPoint
         * @return
         * @throws Throwable
         */
        @Around(CONTROLLER_EXPRESION)
        public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {

            long start = System.currentTimeMillis();
            try {
                String className = joinPoint.getSignature().getDeclaringTypeName();
                String methodName = joinPoint.getSignature().getName();
                Object result = joinPoint.proceed();
                long elapsedTime = System.currentTimeMillis() - start;
                log.debug("Method {}.{} () execution time :  {} ms", className, methodName, elapsedTime);

                return result;
            } catch (IllegalArgumentException e) {
                log.error("Illegal argument {} in {}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getName());
                throw e;
            }
        }

        private String getValue(Object result) {
            String returnValue = null;
            if (null != result) {
                if (result.toString().endsWith("@" + Integer.toHexString(result.hashCode()))) {
                    returnValue = ReflectionToStringBuilder.toString(result);
                } else {
                    returnValue = result.toString();
                }
            }
            return returnValue;
        }
    }

Но при развертывании кода на сервере приложений я получаю этот стек ошибок:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut 

Контроллер, который я хочу отслеживать, находится под org.rest.api.server.controller.Homecontroller - дескриптор метода Java. Нужно ли указывать точный путь или я что-то упускаю?

1 Ответ

0 голосов
/ 24 мая 2019

Ваша проблема связана с дополнительным параметром HttpServletRequest в logBefore;с которым аспект не может связываться.Если вам нужен аргумент из точки соединения;лучше всего осмотреть его в аспекте.Поэтому ваш метод logBefore должен измениться с:

    @Before(CONTROLLER_EXPRESION)
    public void logBefore(JoinPoint joinPoint, HttpServletRequest request) {

        // ASPECT LOGIC
        // ...
    }

на этот:

    @Before(CONTROLLER_EXPRESION)
    public void logBefore(JoinPoint joinPoint) {
        HttpServletRequest request = (HttpServletRequest)joinPoint.getArgs()[0];

        // ASPECT LOGIC
        // ...
    }

Надеюсь, это поможет.

...