11

I am (of course) trying to maintain a project using many constructs I don't know that well. In the course of attempting to figure out the AOP use within Spring, I came across methods with the following annotation:

@Around(value = "@annotation(annotation)")

So @Around means we're doing the 'around' version of the method pointcut in AOP, I understand that. I don't know what the other part means. The Spring documentation gives the following:

@annotation - limits matching to join points where the subject of the join point (method being executed in Spring AOP) has the given annotation

I don't know what that means - "method being executed in Spring AOP" sounds like the advised method, but I don't know how I (or Spring) figure out which methods are being advised. It sounds like it is the methods that have "the given annotation", but if so, what annotation has been given?

What methods are advised by this annotation? And what else does it mean?

arcy
  • 12,845
  • 12
  • 58
  • 103

5 Answers5

17

if you have the following Spring Bean:

@Component
public class foo {

    @com.pkg.Bar      
    void fooMe() {
    }
}

Then the following Advice:

@Around("@annotation(com.pkg.Bar)")

Will invoke the interceptor around fooMe (or any other Spring bean method annotated with @Bar)

The @Transactional annotation is a good example

Ori Dar
  • 18,687
  • 5
  • 58
  • 72
  • That's helpful, but you have "@annotation(com.pkg.Bar)" and I have "@annotation(annotation)", where the second 'annotation' is not itself a specific annotation -- what is this saying about which annotation applies? I've also got "public @interface Y" in the classes using this, and indications that the annotations defined that way are the the ones getting this advice. But what are the rules of it? – arcy Feb 05 '14 at 22:04
  • In `@annotation(annotation)` the annotation is parenthesis `(annotation)` is just a placeholder for the full qualified class name of the annotation – Ori Dar Feb 05 '14 at 22:20
  • So, does that mean this method can advise ANY annotation? – arcy Feb 05 '14 at 23:17
  • It can advice any method annotated with the specified annotation – Ori Dar Feb 05 '14 at 23:19
  • 2
    Well, that's my point - there is no specified annotation. So this is a placeholder, what are the rules about what can be put there? Any annotation at all? Any custom annotation? Any annotation defined in this module? – arcy Feb 05 '14 at 23:35
4

You would have a parameter named annotation, of the appropriate type. It's called bound annotation, see this excerpt from the Spring AOP documentation:

The following example shows how you could match the execution of methods annotated with an @Auditable annotation, and extract the audit code.

First the definition of the @Auditable annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable {
    AuditCode value();
}

And then the advice that matches the execution of @Auditable methods:

@Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")
public void audit(Auditable auditable) {
    AuditCode code = auditable.value();
    // ...
}
2

if you have the following Spring Bean:

@Component
public class foo {
    @com.pkg.Bar      
    void fooMe() {
    }
}

and the following @interface:

public @interface Bar {

    String value() default "default value";
}

you can use the following Advice:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class BarAop {

    @Around(value = "@annotation(bar)") // This 'bar' is one of the parameters of method around(point, bar)
    public Object around(ProceedingJoinPoint point, Bar bar) throws Throwable {

        String value = bar.value();
        System.out.println(value); // will print "default value"

        // execute target method
        Object object = point.proceed();
        System.out.println("return : " + object);

        return object;
    }
}
XianFaLiu
  • 21
  • 1
0

A small tip to complement existing, correct answers.

To make @Aspectannotation work, plain Spring requires @EnableAspectJAutoProxy on the @Configuration class. Or alternatively <aop:aspectj-autoproxy> when XML is used. Spring Boot doesn't need it, because of its auto-configuration.

G. Demecki
  • 10,145
  • 3
  • 58
  • 58
-1
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TimeLoggingAspect {

@Before("timeLoggingAspect()")
public void logBefore(JoinPoint joinPoint){
    System.out.println("Method Name="+joinPoint.getSignature().getName());
    System.out.println("Logging Before...");
}

/*
// Other way for AOP implemetation 
@Pointcut("execution(public void userService())")
  public void timeLoggingAspect(){
}

@After("timeLoggingAspect()")
public void logAfter() throws Exception{
    System.out.println("Logging After...");
    throw new Exception("Error after Logging");
}

@AfterThrowing(pointcut="timeLoggingAspect()",throwing="exception")
public void logAfterThrowingException(Exception exception){
  System.out.println(exception.getLocalizedMessage());
}*/
}


 /** Config class **/
 import org.springframework.stereotype.Component;
 import com.annotation.EnableMethodVisit;
 @Component
 @EnableMethodVisit
 public class UserService {

    public void userService(){
    System.out.println("user service calling......");
  }
 }

 /** Custom Annotation are used **/
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;

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

 }


 /** UserService **/
 import org.springframework.stereotype.Component;

 import com.annotation.EnableMethodVisit;

 @Component
 @EnableMethodVisit
 public class UserService {
    public void userService(){
        System.out.println("user service calling......");
    }
 }

 /** AOP Test **/

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.aop.classes.UserService;
 public class SpringAopTest {

 public static void main(String[] args) {
    AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
       ctx.register(AspectConfig.class);
       ctx.refresh();
       UserService userService = ctx.getBean(UserService.class);
       userService.userService();;
    }
  }
Deepak
  • 1,670
  • 1
  • 20
  • 20