spring-projects / spring-projects/spring-framework
Discover annotations on interface methods for AspectJ annotation pointcuts
Nobody has claimed this yet.
- 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:
- https://stackoverflow.com/questions/6594457/aspectj-annotation-pointcut-not-triggered-for-interface-annotations
- https://stackoverflow.com/questions/7178782/aspectj-pointcut-for-methods-that-override-an-interface-method-with-an-annotati
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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