Java – Spring AOP for interface and for annotated methods within it

aopjavaspring

I have service code like this:

@Component
public class MyService implements com.xyz.WithSession {

    public void someMethodWhichDoesNotNeedAutorization() {
        // code S1
    }

    @com.xyz.WithAuthorization
    public void someMethodWhichNeedAutorization() {
        // code S2
    }
}

and aspect like this:

@Aspect
public class MyAspect {

    @Before("target(com.xyz.WithSession)")
    public void adviceBeforeEveryMethodFromClassImplementingWithSession() {
        // code A1
    }

    @Before("target(com.xyz.WithSession) && @annotation(com.xyz.WithAuthorization)")
    public void adviceBeforeWithAuthorizationMethodFromClassImplementingWithSession() {
        // code A2
    }

Annotation looks like:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface WithAuthorization{
}
  • code A1 is called before code S1 — OK
  • code A1 is called before code S2 — OK
  • code A2 isn't called before code S2 — NOT OK

What am I doing wrong?

Code is written in Java 7 with Spring 3.1.3.

Update

I've tried another way. I use 'Around' advice instead of 'Before' and 'After' to have access to ProceedingJoinPoint. In this advice I check with reflection whether method has annotation 'com.xyz.WithAuthorization' or not:

private boolean isAnnotated(ProceedingJoinPoint proceedingJoinPoint) {
    MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
    return signature.getMethod().isAnnotationPresent(com.xyz.WithAuthorization);
}

My annotation has '@Retention(RetentionPolicy.RUNTIME)' but I see in debugger that annotation is missing on runtime in the method signature. So the problem still exists.

Best Answer

In Spring Reference at this link

e.g. in Spring reference

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

the execution of any method defined by the AccountService interface:

execution(* com.xyz.service.AccountService.*(..))

any join point (method execution only in Spring AOP) where the executing method has an @Transactional annotation:

@annotation(org.springframework.transaction.annotation.Transactional)

I suggest you to use...

@Before("execution(* com.xyz.WithSession.*(..)) && @annotation(authorization)")
public void adviceBeforeWithAuthorizationMethodFromClassImplementingWithSession(WithAuthorization authorization) {
    // code A2
}