0

I want to execute a simple log on all methods of annotated class with a custom annotation. I've created the next annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface FooAnnotation {}

And it's used on a random class:

@FooAnnotation
public class Bar{
  ...
}

Of course my start class has @EnableAspectJAutoProxy annotation

@EnableAspectJAutoProxy
@SpringBootApplication
public class FooApplication {
  public static void main(String[] args) {
    SpringApplication.run(FooApplication.class, args);
  }
}

In the related AspectJ I need to define a @Pointcut to execute @After on all methods of all clases that are annotated with @FooAnnotation

I tried the next AspectJ and it doesn't work

@Slf4j
@Aspect
@Component
public class FooAspectJ{

  @Pointcut("within(x.y.z.FooNotify)")
  private void annotatedWithin() {}

  @Pointcut("@within(x.y.z.FooNotify)")
  private void annotatedAtWithin() {}

  @Pointcut("@annotation(x.y.z.FooNotify)")
  private void annotatedAtAnnotation() {}


  @After("annotatedWithin() || annotatedAtWithin() || annotatedAtAnnotation()")
  private void afterAnnotation(JoinPoint joinPoint){
    log.info("Executed annotated {}", joinPoint.getSignature().getName());
  }

}

I see similar post about this, like @AspectJ pointcut for all methods of a class with specific annotation and aspectj pointcut with annotation parameters, with the same result.

albertoiNET
  • 1,280
  • 25
  • 34

1 Answers1

0

It should be like

@Pointcut("within(@x.y.z.FooNotify *)")

Example:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

@FooNotify
@Repository
public class Bar {
  private static final Logger logger = LoggerFactory.getLogger(Bar.class);

  public String returnSomeString() {
    logger.info("returnSomeString ...");
    int i = returnMeAnInt();
    logger.info("returnMeAnInt returned {}", i);
    return "Hello";
  }

  public void doSomething() {
    logger.info("doSomething ...");
  }

  private int returnMeAnInt() {
    logger.info("returnMeAnInt ...");
    return 4;
  }
}

Aspect:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class BarAspect {
  private static final Logger logger = LoggerFactory.getLogger(BarAspect.class);

  @Pointcut("within(@FooNotify *)")
  public void fooNotifyPointcut() {}

  @After("fooNotifyPointcut()")
  public void afterAnnotation(JoinPoint jp) {
    logger.info("afterAnnotation joinpoint: {}", jp.getStaticPart().getSignature());
  }
}

Annotation:

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(TYPE)
public @interface FooNotify {}

Call:

 bar.returnSomeString();
    bar.doSomething();

Logs:

Bar:13- returnSomeString ...

Bar:24- returnMeAnInt ...

Bar:15- returnMeAnInt returned 4

BarAspect:21- afterAnnotation joinpoint: String com.pkg.Bar.returnSomeString()

Bar:20- doSomething ...

BarAspect:21- afterAnnotation joinpoint: void com.pkg.Bar.doSomething()

For private methods, you have to use full aspectj.

user3487063
  • 3,672
  • 1
  • 17
  • 24