Search code examples
javaspringaopinterceptor

Intercept a method only if that method is called from a certain class?


using AspectJ or Spring Aop (doesn't matter), is it possible to intercept a method only if that method is called from within a certain class?

example:

public class House() {

    String address;

    public House(String address) {
       this.address = address;
    }   
   
    public String getAddress() {
      return this.address();
   }
}


public class BadHouse() {

    public void doNotIntercept() {
      House h = new House("1234");
      h.getAddress();
   }
}

public class GoodHouse() {
     
     public void intercept() {
     House h = new House("4567");
     h.getAddress();
    }

}

public class houseInterceptor() {

     @Before("execution(com.example.House.getAddress(..))")
     // only intercept on GoodHouse.class??? 
     public void beforeGetAddress();

}

Can "within" be used in this circumstance? Thank you


Solution

  • using AspectJ or Spring Aop (doesn't matter), is it possible to intercept a method only if that method is called from within a certain class?

    It is possible with AspectJ (used from within Spring or not, it does not matter), but not with Spring AOP, because you need to

    • either use a combination of call() pointcut and JoinPoint.EnclosingStaticPart (annotation style) or thisEnclosingJoinPointStaticPart (native syntax), if and only if you want to check for the direct caller,
    • alternatively use a combination of call() pointcut and this(), again if and only if you want to check for the direct caller,
    • or use a combination of call() or execution() and cflow() or cflowbelow() pointcuts if you want to check for a possibly indirect caller (e.g. GoodHouseFooHouse).

    The reason why all of the above only work in AspectJ is that Spring AOP neither supports call() nor cflow(), as documented here.

    Can "within" be used in this circumstance?

    No, within() is not helping you in this case.


    Update: Some references to my other answers here:


    Update 2: One of the more unknown corners or Spring AOP is the ControlFlowPointcut class. The Spring manual mentions it briefly without example, but there is a test in the Spring source code and I found an example on a 3rd-party website. It does not help you to directly solve your problem, but I can think of a solution in which you create one such pointcut per allowed source class and link each of the pointcuts to the same advisor implementing the aspect behaviour you want. This would be slow because Spring uses reflection and call stacks, would require some boilerplate code for manually wiring up everything, but it would work.