java - Spring Aspect 的监控方法

标签 java spring-boot spring-mvc aop spring-aop

我想为日志记录实现 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 

我要监控的 Controller 位于 org.rest.api.server.controller.Homecontroller - Java 方法句柄下。我需要指定确切的路径还是我遗漏了其他内容?

最佳答案

你的问题是由于logBefore中的额外参数HttpServletRequest;该方面不能绑定(bind)到。如果您需要来自连接点的参数;最好在方面内检查。所以你的 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
        // ...
    }

希望这对您有所帮助。

关于java - Spring Aspect 的监控方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56278581/

相关文章:

java - JPA和Hibernate注解的关系

java - Spring 启动+JPA : "Unable to locate Attribute with the given name" in a derived class

java - 如何知道 Java 应用程序是否使用 MVC 设计模式?

java - 在 spring 中添加外部 jar - java

java - 无法建立与 Exchange Web 服务的连接 - Java API

amazon-web-services - 实现微服务架构的意义

java - 我只想在少数情况下忽略 JSON 中的字段,这可能吗?

java - tExtractJsonFields Talend,使用正则表达式按长度将列分成多列

java - 如何解析 SOAP 响应?

java - Spring MVC : Sharing context within ear