Search code examples
springaopaspectjspring-aop

Why a @Pointcut name method can't be overloaded?


For Spring Framework 6.0.11 about AOP, having

public class CienciaPointcut {

    @Pointcut("execution(* com.manuel.jordan.service.CienciaService.find*(..))")
    public void cienciaServiceFinds() {

    }

    @Pointcut("execution(* com.manuel.jordan.service.CienciaService.find*(..)) " +
              "&& target(cienciaService) && this(proxy)")
    public void cienciaServiceFinds(CienciaService cienciaService, Object proxy) {

    }

}

Observe that the cienciaServiceFinds method is overloaded and the latter used as:

@AfterThrowing(pointcut="com.manuel.jordan.aop.pointcut.CienciaPointcut.cienciaServiceFinds(cienciaService, proxy)", 
               throwing="exception")

When the app/test is executed it fails at startup with:

Caused by: java.lang.IllegalStateException: Required parameter names not available when parsing pointcut cienciaServiceFinds in type com.manuel.jordan.aop.pointcut.CienciaPointcut
    at org.aspectj.weaver.reflect.Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts(Java15ReflectionBasedReferenceTypeDelegate.java:299)
    at org.aspectj.weaver.ReferenceType.getDeclaredPointcuts(ReferenceType.java:890)
    at org.aspectj.weaver.ResolvedType$PointcutGetter.get(ResolvedType.java:261)
    at org.aspectj.weaver.ResolvedType$PointcutGetter.get(ResolvedType.java:258)
    at org.aspectj.weaver.Iterators$4$1.hasNext(Iterators.java:213)
    at org.aspectj.weaver.Iterators$4.hasNext(Iterators.java:230)
    at org.aspectj.weaver.ResolvedType.findPointcut(ResolvedType.java:767)
    at org.aspectj.weaver.patterns.ReferencePointcut.resolveBindings(ReferencePointcut.java:148)
    at org.aspectj.weaver.patterns.Pointcut.resolve(Pointcut.java:189)
    at org.aspectj.weaver.tools.PointcutParser.resolvePointcutExpression(PointcutParser.java:331)
    at org.aspectj.weaver.tools.PointcutParser.parsePointcutExpression(PointcutParser.java:312)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.buildPointcutExpression(AspectJExpressionPointcut.java:222)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.obtainPointcutExpression(AspectJExpressionPointcut.java:193)
    at org.springframework.aop.aspectj.AspectJExpressionPointcut.getClassFilter(AspectJExpressionPointcut.java:172)
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:226)
    at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:288)
    at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:320)

But when is used

public class CienciaPointcut {

    @Pointcut("execution(* com.manuel.jordan.service.CienciaService.find*(..))")
    public void cienciaServiceFinds() {

    }

    @Pointcut("execution(* com.manuel.jordan.service.CienciaService.find*(..)) " +
              "&& target(cienciaService) && this(proxy)")
    public void cienciaServiceFinds2P(CienciaService cienciaService, Object proxy) {

    }

}

Observe that now is used cienciaServiceFinds and cienciaServiceFinds2P. And of course, used as:

@AfterThrowing(pointcut="com.manuel.jordan.aop.pointcut.CienciaPointcut.cienciaServiceFinds2P(cienciaService, proxy)", 
               throwing="exception")

When the app/test is executed it works fine.

Question

  • Why a @Pointcut named method can't be overloaded?

Solution

  • Following works when the order of pointcut declaration is modified.

    public class CienciaPointcut {
    
        @Pointcut("execution(* com.manuel.jordan.service.CienciaService.find*(..)) " +
                  "&& target(cienciaService) && this(proxy)")
        public void cienciaServiceFinds(CienciaService cienciaService, Object proxy) {
    
        }
    
        @Pointcut("execution(* com.manuel.jordan.service.CienciaService.find*(..))")
        public void cienciaServiceFinds() {
    
        }
    
    }
    

    Not an answer , but my assumption is that , when the AspectJ ecountered the Advice to process , the first pointcut name that match didn't satisfy the argument expectation.

    The point here to note is , this is not about method overloading , rather the order of pointcut processing.

    Attempted with Spring-boot-version : 2.6.4

    Update

    On debug , the issue is within the method tryToDiscoverParameterNames() called from Java15ReflectionBasedReferenceTypeDelegate.getDeclaredPointcuts() where the logic 'tries' to discover the parameters.

    pnames = tryToDiscoverParameterNames(pcs[i]);

    The method tryToDiscoverParameterNames() only compares the method names to get the parameter names through Java15AnnotationFinder.getParameterNames(). This results in incorrect identification of the pointcut method and the downstream logic fails to identify the parameters associated with the pointcut.

    My read is that , this logic is faulty here and the condition check should also consider the arguments part of the pointcut to prevent this exception.