Issue
Is it possible to create a custom annotation that simply tracks invocations of some methods, without having to add a service method call in every method explicit?
@InvocationCounter(path = "/test1") //I'm looking for this
@GetMapping("/person/{id}")
public Person getPerson(Long id) {
//...
}
On every getPerson()
call, I want an invocation counter to record the invocation, like:
@Service
public class InvocationCounterService {
Map<String, AtomicInteger> counter;
public void count(String path) {
if (counter.get(path) == null) counter.put(path, new AtomicInteger()));
counter.get(path).incrementAndGet();
}
@Scheduled(fixedRate = 60000)
public void persist() {
//optionally process or persist the invocations
}
}
Question: how could I possibly tell Spring
to invoke the count()
service method on each annotated controller method?
Solution
The annotation InvocationCounter:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InvocationCounter {
String path();
}
The Aspect InvocationCounterAspect:
@Aspect
@Component
public class InvocationCounterAspect {
@Autowired
InvocationCounterService invocationCounterService;
@Around("@annotation(InvocationCounter)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
InvocationCounter invocationCounter = signature.getMethod().getAnnotation(InvocationCounter.class);
final String path = invocationCounter.path(); //retrieve path from the annotation
invocationCounterService.count(path); //call the counter service
return joinPoint.proceed(); //proceed executing the annotated method
}
}
Answered By - pleft
Answer Checked By - Terry (JavaFixing Volunteer)