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
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
call()
pointcut and JoinPoint.EnclosingStaticPart
(annotation style) or thisEnclosingJoinPointStaticPart
(native syntax), if and only if you want to check for the direct caller,call()
pointcut and this()
, again if and only if you want to check for the direct caller,call()
or execution()
and cflow()
or cflowbelow()
pointcuts if you want to check for a possibly indirect caller (e.g. GoodHouse
→ Foo
→ House
).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:
call()
+ thisEnclosingJoinPointStaticPart
call()
+ JoinPoint.EnclosingStaticPart
call()
+ this()
call()
+ cflow()
, optionally in combination with this()
and also showing how to use thisEnclosingJoinPointStaticPart
thisEnclosingJoinPointStaticPart
is quicker for the direct caller than Throwable.getStackTrace()
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.