javaaspectjpointcut

2 advices colliding on the same fucntion


Hei, I started learning Aspectj and I have built 2 aspects. Both aspects have a pointcut that match the same function, and both aspects have an around advice that will do something on that pointcut. However only one advice will be "executed", and I do not understand why.

let me show you:

@Aspect
public class secondAspect {
    @Pointcut("call(  * main.*(..))")
    public void pointCutThatMatchesEveryFunctionFromMain(){

    }
    @Around("pointCutThatMatchesEveryFunctionFromMain()")
    public void adviceOnPointCutThatMatchesEveryFunctionFromMain(JoinPoint jp){
        System.out.println("A method was called");
        System.out.println(jp.getTarget().toString());
    }
}

that is the second aspect

@Aspect
public class firstAspect {


    @Pointcut("call( public * main.*(..)) && args(x,y)")
    public void pointCutOnMainClassIntArgs(int x, int y) {

    }

    @Pointcut("call( public * main.*(..)) && args(x,y)")
    public void pointCutOnMainClassFloatArgs(float x, float y) {

    }


    @Around("pointCutOnMainClassIntArgs(x,y)")
    public void doSomethingOnThisPointCut(JoinPoint pjp, int x, int y) {
        System.out.println(String.format("The method name is %s and was called with parameteres %d %d", pjp.getTarget().toString(), x, y));
    }


    @Around("pointCutOnMainClassFloatArgs(x,y)")
    public void doSomethingOnThisPointCutWithFloatArgs(JoinPoint pjp, float x, float y) {
        System.out.println(String.format("The method name is %s and was called with parameteres %f %f", pjp.getTarget().toString(), x, y));
    }


}

the first aspect


public class main {
    public static void main(String[] args) {
        main maine = new main();
        maine.calculate(2,3);
        maine.calculate(2.0f,5.0f);
    }
    public void calculate(int x, int y){
        System.out.println(x+y);
    }
    public void calculate(float x, float y){
        System.out.println(x+y);
    }

}

and this is the class that i want to modify. Only the secondAspect's adivce is executed. And I don't get it why.


Solution

  • The short answer is: Change your advice type from @Around to @Before, then it works and the console output will turn into:

    A method was called
    main@5f341870
    The method name is main@5f341870 and was called with parameteres 2 3
    The method name is main@5f341870 and was called with parameteres 2,000000 3,000000
    5
    A method was called
    main@5f341870
    The method name is main@5f341870 and was called with parameteres 2,000000 5,000000
    7.0
    

    Caveat: If you inspect the above log output, you will notice that your advice doSomethingOnThisPointCutWithFloatArgs also matches the method with the int parameters, which probably was not your intention. You need to be more precise than main.*(..) and better use main.*(int, int) vs. main.*(float, float) in your pointcuts.

    The long answer is: You should read an AspectJ tutorial. For example, an @Around advice needs

    Some more suggestions:

    How about this?

    package de.scrum_master.app;
    
    public class Application {
      public static void main(String[] args) {
        Application application = new Application();
        application.calculate(2, 3);
        application.calculate(2.0f, 5.0f);
      }
    
      public void calculate(int x, int y) {
        System.out.println(x + y);
      }
    
      public void calculate(float x, float y) {
        System.out.println(x + y);
      }
    }
    
    package de.scrum_master.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect
    public class FirstAspect {
      @Before("execution(public !static * *(int, int)) && args(x, y) && target(targetInstance)")
      public void publicNonStaticMethodsWith2IntParameters(JoinPoint joinPoint, int x, int y, Object targetInstance) {
        System.out.printf("[FA] %s -> %s [%s, %s]%n", joinPoint, targetInstance, x, y);
      }
    
      @Before("execution(public !static * *(float, float)) && args(x, y) && target(targetInstance)")
      public void publicNonStaticMethodsWith2FloatParameters(JoinPoint joinPoint, float x, float y, Object targetInstance) {
        System.out.printf("[FA] %s -> %s [%s, %s]%n", joinPoint, targetInstance, x, y);
      }
    }
    
    package de.scrum_master.aspect;
    import java.util.Arrays;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    
    @Aspect
    public class SecondAspect {
      @Before("execution(public !static * *(..)) && target(targetInstance)")
      public void publicNonStaticMethods(JoinPoint joinPoint, Object targetInstance) {
        System.out.printf("[SA] %s -> %s %s%n", joinPoint, targetInstance, Arrays.deepToString(joinPoint.getArgs()));
      }
    }
    
    [FA] execution(void de.scrum_master.app.Application.calculate(int, int)) -> de.scrum_master.app.Application@6c3708b3 [2, 3]
    [SA] execution(void de.scrum_master.app.Application.calculate(int, int)) -> de.scrum_master.app.Application@6c3708b3 [2, 3]
    5
    [SA] execution(void de.scrum_master.app.Application.calculate(float, float)) -> de.scrum_master.app.Application@6c3708b3 [2.0, 5.0]
    [FA] execution(void de.scrum_master.app.Application.calculate(float, float)) -> de.scrum_master.app.Application@6c3708b3 [2.0, 5.0]
    7.0