Spring-AOP pointcut not working?
Below is my code snippet:
ServiceImpl.java
@Service
public class ServiceImpl implements Service {
private Response worker(Audit send) throws ArgumentException {
System.out.println("STEP_1");
worker(send.getRequest(), send.getId());
}
private Response worker(Request request, String id) throws ArgumentException {
System.out.println("STEP_2");
try {
//throwing some exception
} catch (Exception e) {
System.out.println("STEP_3");
}
}
}
Now I want that whenever NullPointerException
thrown out of a method worker(Request request, String id)
as shown above, I want to perform a specific task. For this, I wrote an Aspect class that is as follows:
MyAspect.java
@Aspect
@Component
public class MyAspect{
@Pointcut("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
private void someOperation(Request request) {}
@Before("someOperation(request)")
public void process(Request request) {
System.out.println("SUCCESS");
}
@AfterThrowing("com.xyz.myapp.ServiceImpl.worker() && args(request,..)")
public void doRecoveryActions() {
System.out.println("EXCEPTION_SUCCESS");
}
}
Current output:
STEP_1 STEP_2 STEP_3
Desired output:
STEP_1 STEP_2 STEP_3 SUCCESS EXCEPTION_SUCCESS
As you can see, it MyAspect.java
does not start, so it does NOT print the values. What could be causing this?
Note:
-
I tried to make the worker as public class but it didn't work.
-
Also tried changing the name of the methods to fix the overloading issue which didn't work either.
-
Tried various pointcut expressions all in vain.
-
There are other aspect classes in my application that work absolutely fine.
source to share
You've made a typical Spring AOP beginner mistake: you assume it works for private methods, but as the documentation clearly states, it doesn't. Spring AOP is based on dynamic proxies and they only work for public methods when implementing interfaces through JDK proxies, and additionally for secure and batch methods when using CGLIB proxies.
You must make the method worker()
public if you want to intercept it from an aspect.
PS: Full-fledged AspectJ also works for private methods, but switching to a different AOP structure would be overkill.
Update: You also have other problems in your code:
- The first method
worker
, even if you make it public, returns nothing. The last statement should bereturn worker(send.getRequest(), send.getId());
, not onlyworker(send.getRequest(), send.getId());
. - Your pointcut
com.xyz.myapp.ServiceImpl.worker()
will never match because it has an empty argument list, but your method has arguments.args()
won't help you. - The syntax of your pointcut is also incorrect as it doesn't specify the return type for the method, not even
*
. Also, the method name itself is not enough, it must be wrapped in the actual pointcut type, for exampleexecution()
. That is, you want to write something like:
@Pointcut("execution(* com.xyz.myapp.ServiceImpl.worker(..)) && args(request, ..)")
private void someOperation(Request request) {}
source to share
To intercept a method that throws an exception, you can use this code (only works if the methods are public):
@AfterThrowing(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()",throwing="ex")
public void doRecoveryActions(NullPointerException ex) {
// ...
}
Source: Spring AOP
source to share