I'm trying to time methods via annotations, I've found plenty of information about how to time executions of things, and I feel like I'm close but my console isn't getting any output.
The jist of what I'm trying to do
public static void main(String[] args) {
Simpleton simp = new Simpleton();
simp.howLongDidThisTake();
}
@MethodTimer
public void howLongDidThisTake() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
My Interface
package com.lixar.apba.aop.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodTimer{
}
and my advice/service class for the functionality attached to it.
package com.lixar.apba.aop.annotations;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Aspect
@Component
public class MethodTimerService {
Logger logger = LoggerFactory.getLogger(MethodTimerService.class);
static Map<String, Long> loggedMethods = new HashMap<>();
String signature = null;
@Around("@annotation(com.lixar.apba.aop.annotations.MethodTimer)")
public Object methodTimer(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
Object callback = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
insertLoggedExecution(proceedingJoinPoint, startTime, endTime);
return callback;
}
private void insertLoggedExecution(ProceedingJoinPoint pjp, long startTime, long endTime) {
signature = String.valueOf(pjp.getSignature());
long calculatedTime = getCalculatedTime(startTime, endTime);
loggedMethods.put(String.valueOf(pjp.getSignature()), calculatedTime);
System.out.println("Method name: " + signature + " : TotalExecutionTime: " + calculatedTime);
}
private long getCalculatedTime(long startTime, long endTime) {
long calculatedTime = endTime - startTime;
if(loggedMethods.containsKey(signature)) {
calculatedTime = endTime - startTime + loggedMethods.get(signature);
}
return calculatedTime;
}
public static void outPutLoggedExecution() {
for(var log : loggedMethods.entrySet()) {
System.out.println("Method name: " + log.getKey() + " : TotalExecutionTime: " + log.getValue());
}
}
}
The annotation is never being called, how can I fix this?
Configuration
First of all, you need to configure your IDE to work with AspectJ.
1. Configuration for IntelliJ
3. Spring configuration documentation
Code changes
@Pointcut
Declare @Pointcut
for your custom @MethodTimer
annotation
@Pointcut("@annotation(methodTimer)")
public void callMethod(MethodTimer methodTimer) { }
Pointcut: A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP: Spring uses the AspectJ pointcut language by default.
Bind Pointcut
with your @Around
advice. Also, you need to restrict @Around
advice only for execution, otherwise method will be called twice: Why does AspectJ @Around advice execute twice?
@Around("callMethod(methodTimer) && execution(* *(..))")
public Object methodTimer(ProceedingJoinPoint proceedingJoinPoint, MethodTimer methodTimer) throws Throwable {
long startTime = System.currentTimeMillis();
Object callback = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
insertLoggedExecution(proceedingJoinPoint, startTime, endTime);
return callback;
}
@Around("@annotation(methodTimer) && execution(* *(..)) ")
public Object methodTimer(ProceedingJoinPoint proceedingJoinPoint, MethodTimer methodTimer) throws Throwable {
long startTime = System.currentTimeMillis();
Object callback = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
insertLoggedExecution(proceedingJoinPoint, startTime, endTime);
return callback;
}
Full code:
public static void main(String[] args) {
Simpleton simp = new Simpleton();
simp.howLongDidThisTake();
}
public class Simpleton {
@MethodTimer
public void howLongDidThisTake() {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodTimer{
}
@Aspect
@Component
public class MethodTimerService {
static Map<String, Long> loggedMethods = new HashMap<>();
String signature = null;
@Pointcut("@annotation(methodTimer)")
public void callMethod(MethodTimer methodTimer) { }
@Around("callMethod(methodTimer) && execution(* *(..)) ")
public Object methodTimer(ProceedingJoinPoint proceedingJoinPoint, MethodTimer methodTimer) throws Throwable {
long startTime = System.currentTimeMillis();
Object callback = proceedingJoinPoint.proceed();
long endTime = System.currentTimeMillis();
insertLoggedExecution(proceedingJoinPoint, startTime, endTime);
return callback;
}
private void insertLoggedExecution(ProceedingJoinPoint pjp, long startTime, long endTime) {
signature = String.valueOf(pjp.getSignature());
long calculatedTime = getCalculatedTime(startTime, endTime);
loggedMethods.put(String.valueOf(pjp.getSignature()), calculatedTime);
System.out.println("Method name: " + signature + " : TotalExecutionTime: " + calculatedTime);
}
private long getCalculatedTime(long startTime, long endTime) {
long calculatedTime = endTime - startTime;
if(loggedMethods.containsKey(signature)) {
calculatedTime = endTime - startTime + loggedMethods.get(signature);
}
return calculatedTime;
}
public static void outPutLoggedExecution() {
for(Map.Entry<String, Long> log : loggedMethods.entrySet()) {
System.out.println("Method name: " + log.getKey() + " : TotalExecutionTime: " + log.getValue());
}
}
}
Program execution result
Method name: void Simpleton.howLongDidThisTake() : TotalExecutionTime: 55
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.