简体   繁体   中英

Spring AOP Pointcut for methods invoked on field with annotation

I'm writing an aspect for making that possible for dependencies from external libraries to return values that are correctly formatted for my application.

With this in mind, I've created an annotation with name @SafeReturns. I wire this class from the external library with the help of spring and in addition, I add my annotation.

@SafeReturns
@Autowired
public PermissionsClient client; 

Now I try to make an aspect of it, but unfortunately, I can't catch all the calls to all the methods on the field annotated with this annotation. I tried different pointcuts. eg

@Pointcut("execution(@myApp.SafeReturns * *(..))")

@Around("safeReturnsPointCut()")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {    
}

None of them helps me to achieve the behaviour of catching all the methods. Is there a way to catch them?

There are several problems with your approach and your assumptions about aspect syntax and execution logic:

  • You are using Spring AOP, but that one only works with Spring-managed beans/components due to its proxy-based nature, as is well documented in the Spring AOP manual . It does not work with non-Spring third-party code.

  • In order to target third-party code you need to use full AspectJ via LTW (load-time weaving). The Spring AOP manual also explains how to configure LTW .

  • Your pointcut says to target all method executions (of Spring components, if you are using Spring AOP) where the methods are annotated by SafeReturns . Neither with Spring AOP nor with AspectJ can you expect this syntax to apply to objects that happen to be assigned to instance member variables with a certain annotation. So your expectations of how you dream AOP to work and how it really does are quite divergent.

My suggestion is to switch to AspectJ via LTW and then write pointcuts which either target external method execution() s directly or to solve the problem indirectly by routing your external calls through annotated facades and target them with your pointcuts. This would even work with Spring AOP if the facades are Spring components.

There also is a direct way of solving this with advanced AspectJ + some manual bookkeeping. You can use set() pointcuts in order to find out when objects are assigned to your annotated fields (or unassigned later). Then you can have the aspect do manual bookkeeping of assigned objects and make sure that whatever your aspect advices do is only triggered if the object in question happens to be assigned to an annotated member variable. This works, I also have done that in the past. But it means you have to weave all of your application's method calls and then dynamically decide via look-ups in your bookkeeping whether or not the code should be executed or not, because there yould be object instances which are not assigned to any of your annotated fields. This incurs a certain performance penalty because this kind of thing cannot be determined during compile time by any aspect weaver. Please see my answer here for sample code for the manual bookkeeping thing.

I hope that my explanation was not too complicated, but your issue is quite technical and intricate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM