繁体   English   中英

Spring AOP - 类和方法的自定义注解

[英]Spring AOP - Custom Annotation for Class and Method

现有答案很好地解释了如何使用自定义注释进行方法执行时间记录。 我想知道是否有办法对类和方法使用相同的注释,但切入点应该在使用的地方不同。

@LogExecutionTime
public class MyServiceImpl implements MyService {

    public void run(){
       // logic
    }

    public void walk(){
       // logic
    }

    private void breather(){
       // logic
    }
}

如果对类使用注解,类中的所有方法都应考虑用于方面类中的执行时间记录(如execution(* com.me.package.MyServiceImpl.*(..)) )。 但是,如果 Annotation 仅用于类内部的单个方法,则还应考虑 Aspect Logging 类中的唯一方法。 (例如execution(* com.you.package.YourServiceImpl.forward(..)) )。

public class YourServiceImpl implements YourService {

    @LogExecutionTime
    public void forward(){
       // logic
    }

    @LogExecutionTime
    public void backward(){
       // logic
    }

    private void upward(){
       // logic
    }
}

注解类

package com.myproj.core.utils.annotation;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;

@Retention(RUNTIME)
public @interface LogExecutionTime {

}

注释的方面类(使用@kriegaex 建议的切入点)

package com.myproj.core.utils;

import java.time.Duration;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import java.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Aspect class to Log Method Execution time
 */
@Aspect
public class MyMethodExecutionLoggingAspect {
    
    private static final Logger LOG = LoggerFactory.getLogger(MyMethodExecutionLoggingAspect.class);
    
    /**
     * This method will log Method Execution Time
     * 
     * @param joinPoint
     * @return object
     * @throws Throwable
     */
    @Around("execution(* (@com.myproj.core.utils.annotation.LogExecutionTime *).*(..)) || execution(@com.myproj.core.utils.annotation.LogExecutionTime * *(..))")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {

        String className = joinPoint.getTarget().getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        Instant start = Instant.now();

        try {
            return joinPoint.proceed();
        } finally {

            long end = Duration.between(start, Instant.now()).toMillis();

            if (end > 0) {
                LOG.debug("METHOD EXECUTION TIME LAPSED: {}ms | {}.{}", end, className, methodName);
            }
        }

    }
    
}

spring.xml 中的 Spring Bean 定义

<bean class="com.myproj.core.utils.MyMethodExecutionLoggingAspect" />

您使用@annotation()示例代码没有意义,因为您没有指定方法注释类型。 它应该类似于@annotation(fully.qualified.AnnotationType)

匹配类注释要使用@within(fully.qualified.AnnotationType)如所描述这里

所以你可以使用像这样的切入点

@annotation(fully.qualified.AnnotationType)
  || @within(fully.qualified.AnnotationType)

或者,根据我在此处的回答,您还可以使用更神秘的版本

execution(* (@fully.qualified.AnnotationType *).*(..))
  || execution(@fully.qualified.AnnotationType * *(..))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM