1

let's consider the following situation.

@interface LoggedMethodInvocation{}

@LoggedMethodInvocation
@interface MonitoredMethodInvocation{}

I would like the @MonitoredMethodInvocation annotation implying the @LoggedMethodInvocation annotation.

class LoggingAOPConfig {
   
    @Pointcut("@annotation(LoggedMethodInvocation)")
    public void servicePointcut() {
    }

    @Around("servicePointcut()")
    public Object logMethodInvocation(ProceedingJoinPoint pjp) throws Throwable {
        // log the method invocation...
    }
}
class MonitoringAOPConfig {

    @Pointcut("@annotation(MonitoredMethodInvocation)")
    public void servicePointcut() {
    }

    @Around("servicePointcut()")
    public Object monitorResponseTime(ProceedingJoinPoint pjp) throws Throwable {
        // add some meters to the method invocation
    }
}

Now I would like to introduce some method, which shall be both monitored and logged. And I would like to annotate the method only with one annotation, namely @MonitoredMethodInvocation.

class SomeService {
   
    @MonitoredMethodInvocation
    Object someMethod(Object requestPayload) {
        // ...
        return responsePayload;
    }
}

However it doesn't play, the logging aspect is not taken into the account.

There is spring's AnnotationUtils.findAnnotation which offers the needed functionality (of recognizing, whether the @LoggedMethodInvocation shall be considered). However, I don't know how to put this into the pointcut configuration.

How shall I modify the logging AOP config so it will recognize the logging annotation even if it is hidden behind the @MonitoredMethodInvocation?

miro
  • 131
  • 2
  • 9
  • 1
    1. Please read through SO Q&A : [Is there something like Annotation Inheritance in java?](https://stackoverflow.com/questions/7761513/is-there-something-like-annotation-inheritance-in-java) to get a grip on why this code is not working as you expect 2. If the requirement is to log along with monitor we can also call a helper method to log from both aspects . Another way is to have the same aspect class for both pointcuts and a single `log()` method gets called from both advises. 3. `MergedAnnotations.from(.. )` could be used instead of `AnnotationUtils.findAnnotation(..)` – R.G May 13 '22 at 03:35
  • 1
    `MethodSignature ms = (MethodSignature)pjp.getSignature(); MergedAnnotations annotations = MergedAnnotations.from(ms.getMethod());` could be used within an aspect advise to introspect the annotations for the method and perform the logic required – R.G May 13 '22 at 03:37

1 Answers1

1

Using the syntax from https://stackoverflow.com/a/38209801/3394495, this should work for your case:

class LoggingAOPConfig {
   
    @Pointcut("@annotation(LoggedMethodInvocation)")
    public void servicePointcut() {
    }

    @Pointcut("execution(@(@LoggedMethodInvocation *) * *(..))")
    public void metaServicePointcut() {
    }

    @Around("servicePointcut() || metaServicePointcut()")
    public Object logMethodInvocation(ProceedingJoinPoint pjp) throws Throwable {
        // log the method invocation...
    }
}
cheshire
  • 190
  • 2
  • 4