简体   繁体   English

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

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

Existing answers gives nice explanation on how to use Custom Annotation for method execution time logging.现有答案很好地解释了如何使用自定义注释进行方法执行时间记录。 I am wondering if there is way to use same annotation for both Class and Method, but Pointcut should be different where it is used.我想知道是否有办法对类和方法使用相同的注释,但切入点应该在使用的地方不同。

@LogExecutionTime
public class MyServiceImpl implements MyService {

    public void run(){
       // logic
    }

    public void walk(){
       // logic
    }

    private void breather(){
       // logic
    }
}

If Annotation is used for class all methods inside class should be considered for Execution Time Logging in Aspect Class (like execution(* com.me.package.MyServiceImpl.*(..)) ).如果对类使用注解,类中的所有方法都应考虑用于方面类中的执行时间记录(如execution(* com.me.package.MyServiceImpl.*(..)) )。 However if the Annotation is only used for single method inside the class, it is should also consider that only method in Aspect Logging Class.但是,如果 Annotation 仅用于类内部的单个方法,则还应考虑 Aspect Logging 类中的唯一方法。 (like execution(* com.you.package.YourServiceImpl.forward(..)) ). (例如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
    }
}

Annotation Class注解类

package com.myproj.core.utils.annotation;

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

import java.lang.annotation.Retention;

@Retention(RUNTIME)
public @interface LogExecutionTime {

}

Aspect Class for Annotation (using pointcuts as suggested by @kriegaex)注释的方面类(使用@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 Bean Definition in spring.xml spring.xml 中的 Spring Bean 定义

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

Your sample code with @annotation() does not make sense because you do not specify a method annotation type.您使用@annotation()示例代码没有意义,因为您没有指定方法注释类型。 It should be something like @annotation(fully.qualified.AnnotationType) instead.它应该类似于@annotation(fully.qualified.AnnotationType)

For matching class annotations you want to use @within(fully.qualified.AnnotationType) , as described here .匹配类注释要使用@within(fully.qualified.AnnotationType)如所描述这里

So you could use a pointcut like所以你可以使用像这样的切入点

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

Alternatively, according to my answer here , you could also use the more cryptic version或者,根据我在此处的回答,您还可以使用更神秘的版本

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

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

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