spring-projects / spring-projects/spring-framework

Discover annotations on interface methods for AspectJ annotation pointcuts

Open
#22,311 8 comments 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: core type: enhancement
Dominant language
Java
Stars
60.2k
Forks
38.8k
Avg merge
5d 2h
Merged PRs (30d)
27

Description

Affects: spring-aop:5.0.9.RELEASE, spring-boot-starter-aop:2.0.5.RELEASE

public interface FooService {

  @MyAnnotation 
  void hello();
}

public class FooServiceImpl implements FooService {

  void hello();
}
public class MyAspect {

  @Pointcut("@annotation(MyAnnotation")
     public void myPointcut() {
   }

  @Around("myPointcut()")
  public Object around(ProceedingJoinPoint pjp) throws Throwable {
     ...
  }
}
@Configuration
public class MyAopConfiguration {
    @Bean
    public MyAspect myAspect () {
        return new MyAspect();
    }
}

Using spring-aop like the code above, it doesn't work, around(ProceedingJoinPoint pjp) never executes.

If put the @MyAnnotation on the implemented method of FooServiceImpl, it works.

public interface FooService { 

  void hello();
}

public class FooServiceImpl  implements FooService {

  @MyAnnotation
  void hello();
}

Learned from two questions in Stack Overflow:

According to the Java 5 specification, non-type annotations are not inherited, and annotations on types are only inherited if they have the @Inherited meta-annotation.

It's seems that it's impossible in spring-aop.

I tried the code without spring-aop, only using aspectjweaver 1.7.4, and adding an aop.xml in resources/META-INF:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
    <aspects>
        <aspect name="com.xxx.MyAspect"/>
    </aspects>
    <weaver options="-verbose -showWeaveInfo -Xset:weaveJavaxPackages=true" />
</aspectj>

and adding JVM parameter:

-javaagent:xxx/aspectjweaver-1.7.4.jar

It works no matter the @MyAnnotation is on the interface or class. And then in around(ProceedingJoinPoint pjp), I can get the @MyAnnotation with the API of pjp, like this:

MethodSignature signature = (MethodSignature)joinPoint.getSignature();
Class<?> targetClass = pjp.getTarget().getClass();
Method method = targetClass.getDeclaredMethod(signature.getName(), signature.getMethod().getParameterTypes());
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);

or

Class<?>[] interfaces = targetClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
   Method method = targetClass.getDeclaredMethod(signature.getName(), 
   signature.getMethod().getParameterTypes());
   MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);
}

So I think spring-aop may also have way to solve this problem, since it's a common use case for users to add annotation on the method of interface.

Something in AopUtils#getMostSpecificMethod, AspectJExpressionPointcut#getShadowMatch(Method targetMethod, Method originalMethod) may be about, I'm not sure.

Could you please give some help?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading AopUtils#getMostSpecificMethod and AspectJExpressionPointcut#getShadowMatch(Method targetMethod, Method originalMethod), which the issue identifies as possible entry points. Reproduce the interface-method annotation example and inspect existing Spring AOP tests for annotation pointcuts. Done means Spring AOP matches @annotation pointcuts when the annotation is declared on the implemented interface method, with regression coverage.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.