Search code examples
javaspringspring-bootaop

Aspect for methods in extended class does not work


I try to apply aspect for two methods that are in abstract class, that is extended by another class.

Problem is that pointcut i am using doesn't work.

Code looks like this:

public class ClassA extends ClassB {

    public void testMethod(String testString, Integer testInt){
        extendedClassMethod1(testString, testInt);
        extendedClassMethod2(testString, testInt);
    }
}

public abstract class ClassB {

   public String extendedClassMethod1(String testString, Integer testInteger) {
        return testString + testString.toString();
    }

    public String extendedClassMethod2(String testString, Integer testInteger) {
        return testString + testString.toString();
    }
}

@Aspect
public class AspectClass {

   @AfterReturning(
            value = "execution(* com.test.ClassB.*(..)) && args(testString, testInteger)",
            returning = "result")
    public void aspectMethod(JoinPoint joinPoint, String testString, Integer testInteger, String result){
        // do something
    }
}

Goal is to create aspect thay will work when extendedClassMethod1 or extendedClassMethod2 is used in classes (f.e. ClassA) that extends ClassB.

Another thing is that Intellij shows that aspect method should be applied to this two methods, but in runtime it does not.


Solution

  • I commented:

    If you really use AspectJ (e.g. via load-time weaving configuration) and not Spring AOP, it works as you wish. If it does not work, you are not using AspectJ. It is as simple as that. If you want to challenge my statement, just provide an MCVE incl. Maven POM and ideally on GitHub, so I can just clone and run the application, e.g. via Spring Boot. BTW, in order to make this work with POJOs you don't need Spring at all. I tested your code outside of Spring.

    In order to support my statement, here is my MCVE using POJOs + AspectJ:

    Base class (why ever abstract because there are no abstract methods):

    package de.scrum_master.app;
    
    public abstract class ClassB {
      public String extendedClassMethod1(String testString, Integer testInteger) {
        return testString + " / " + testInteger.toString();
      }
    
      public String extendedClassMethod2(String testString, Integer testInteger) {
        return testString + " / " + testInteger.toString();
      }
    }
    

    (Concrete) subclass:

    package de.scrum_master.app;
    
    public class ClassA extends ClassB {
      public void testMethod(String testString, Integer testInt) {
        extendedClassMethod1(testString, testInt);
        extendedClassMethod2(testString, testInt);
      }
    }
    

    Driver application:

    package de.scrum_master.app;
    
    public class Application {
      public static void main(String[] args) {
        ClassA classA = new ClassA();
        classA.extendedClassMethod1("eleven", 11);
        classA.extendedClassMethod2("twenty-two", 22);
        classA.testMethod("thirty-three", 33);
      }
    }
    

    Aspect:

    package de.scrum_master.aspect;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    
    @Aspect
    public class AspectClass {
      @AfterReturning(
        value = "execution(* de.scrum_master.app.ClassB.*(..)) && args(testString, testInteger)",
        returning = "result"
      )
      public void aspectMethod(JoinPoint joinPoint, String testString, Integer testInteger, String result) {
        System.out.println(joinPoint);
        System.out.println("  testString = " + testString);
        System.out.println("  testInteger = " + testInteger);
        System.out.println("  result = " + result);
      }
    }
    

    Console log:

    execution(String de.scrum_master.app.ClassB.extendedClassMethod1(String, Integer))
      testString = eleven
      testInteger = 11
      result = eleven / 11
    execution(String de.scrum_master.app.ClassB.extendedClassMethod2(String, Integer))
      testString = twenty-two
      testInteger = 22
      result = twenty-two / 22
    execution(String de.scrum_master.app.ClassB.extendedClassMethod1(String, Integer))
      testString = thirty-three
      testInteger = 33
      result = thirty-three / 33
    execution(String de.scrum_master.app.ClassB.extendedClassMethod2(String, Integer))
      testString = thirty-three
      testInteger = 33
      result = thirty-three / 33