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.*(..))
). 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. (like 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)
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
<bean class="com.myproj.core.utils.MyMethodExecutionLoggingAspect" />