18

I'm using Spring AspectJ for logging method execution statistics, however, I want to exclude some classes and methods from this without changing the pointcut expression.

To exclude certain methods I created a custom annotation which I use to filter out. However I'm unable to do the same with classes.

Here is my aspect definition -

@Around("execution(* com.foo.bar.web.controller.*.*(..)) "
            + "&& !@annotation(com.foo.bar.util.NoLogging)")
public Object log(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    // logging logic here
}

NoLogging is my custom annotation for excluding methods.

So how can I filter out certain classes without changing pointcut expression and without adding new advisors?

cb4
  • 6,689
  • 7
  • 45
  • 57
Harshil Sharma
  • 2,016
  • 1
  • 29
  • 54
  • i think that's not possible, execution will match your definition and it is loaded at begining. Maybe you can try to create a new @Around aspect and check if it overrides previous one. But I am not sure of it. – duardito Aug 08 '16 at 07:05

2 Answers2

29

Okay so I found the solution - use @target PCD (pointcut designators) to filter out classes with specific annotation. In this case I already have the @NoLogging annotation so I can use that. The updated pointcut expression will then become as follows -

@Around("execution(* com.foo.bar.web.controller.*.*(..)) "
            + "&& !@annotation(com.foo.bar.util.NoLogging)" 
            + "&& !@target(com.foo.bar.util.NoLogging)")
public Object log(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
    // logging logic here
}

Explanation -

execution(* com.foo.bar.web.controller.*.*(..)) - all methods of all classes in c.f.b.w.controller package

"&& !@annotation(com.foo.bar.util.NoLogging)" - which do NOT have @NoLogging annotation on them

"&& !@target(com.foo.bar.util.NoLogging)" - and whose class also does NOT have @NoLogging annotation.

So now I simply have to add @NoLogging annotation to any class whose methods I want to be excluded from the aspect.

More PCD can be found in Spring AOP documentation - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-pointcuts-designators

Harshil Sharma
  • 2,016
  • 1
  • 29
  • 54
  • Hi, is it possible to also add your @NoLogging custom annotation implementation, I am having trouble to filter out methods from similar avoid logging scenario. – harmonious May 24 '18 at 11:13
  • 2
    @harmonious the annotation doesn't contain any logic. You can find it over here - https://github.com/harshilsharma63/controller-logger/blob/master/src/main/java/io/github/logger/controller/annotation/NoLogging.java – Harshil Sharma May 25 '18 at 00:26
  • @harmonious also, I've created an open source library for handling all of AOP based logging logic. You can check it out at https://github.com/harshilsharma63/controller-logger. Maybe it already fulfills your task? – Harshil Sharma May 25 '18 at 00:28
  • Thanks @harshil-sharma I got it to work with: `@Target(ElementType.METHOD ) public @interface NoLogging { }` – harmonious May 27 '18 at 14:10
4

As per Spring AOP documentation

PCD can be &&'ed, ||'ed, and ! (negated) too.

So I guess this is more of trial and error exercise. I think you can try something like && !@within @within is applicable for types. Or you can try !@target

But then again I think it could be tricky.

Another approach: declare two pointcut definitions and combine them. And example, here on the documentation page. I would try this first. Something like

@Pointcut(executionPC() && nonAnnotatedClassesPC() && nonAnnotatedMethodsPC())

Disclaimer: As I said, this looks more like trial and error. And I don't have a clear working example.

Atul
  • 2,673
  • 2
  • 28
  • 34