Spring AOP does not work when method is called inside bean

I have several Aspects encoded in my application. All others work, except for the following.

Service interface

package com.enbiso.proj.estudo.system.service; ... public interface MessageService { ... Message reply(Message message); Message send(Message message); ... } 

Service implementation

 package com.enbiso.proj.estudo.system.service.impl; .... @Service("messageService") public class MessageServiceImpl implements MessageService { ... @Override public Message reply(Message message) { ... return this.send(message); } @Override public Message send(Message message) { ... } } 

Aspect

 @Aspect @Component public class NewMessageAspect { ... @AfterReturning(value = "execution(* com.enbiso.proj.estudo.system.service.impl.MessageServiceImpl.send(..))", returning = "message") public void perform(Message message){ ... } } 

When I try to execute the send method, the debug point does not fall into the perform aspect.

UPDATE

I did some research and found that this does not work when the send method is called from the reply method, as shown below

 @Autowire MessageService messageService; ... messageService.reply(message); 

But if I call the messageService.send(message) method, it works fine. But since the response method calls the send method internally, should it not also refer to the aspect?

I have no idea what I did wrong. Please help me.

+3
source share
3 answers

Thanks, jst , for clearing things up. Just for informational purposes of the future developer in SO, I am posting a complete answer to this question


Suppose there is a bean from SimplePojo
 public class SimplePojo implements Pojo { public void foo() { this.bar(); } public void bar() { ... } } 

When we call the foo() method, it re-calls the bar() method inside it. Even if the foo() method is called from the AOP proxy, the internal call to bar() does not extend to the AOP proxy.

Proxy calls

So in the end, it does, if there are any tips related to the bar() method, so as not to cause a call

Decision

Use AopContext.currentProxy() to call the method. Unfortunately, this connects logic with AOP.

 public void foo() { ((Pojo) AopContext.currentProxy()).bar(); } 

Link:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

+6
source

You use the Spring AOP constraint when you start it. You can basically get around it using AopContext.currentProxy (), refactoring code into different beans, or use ApsectJ's full weave.

See explanation here and workarounds. http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

+2
source

I think the problem is the @args condition.

Documentation

Spring says the following:

 @args - limits matching to join points (the execution of methods when using Spring AOP) where the runtime type of the actual arguments passed have annotations of the given type(s) 

Therefore, the @args parameter must be a type expression. So the correct pointcut expression

 @AfterReturning(value = "execution(* com.enbiso.proj.estudo.system.service.impl.MessageServiceImpl.send(..)) && args(com.enbiso.proj.estudo.system.service.impl.Message") 

or simply

 @AfterReturning(value = "execution(* com.enbiso.proj.estudo.system.service.impl.MessageServiceImpl.send(com.enbiso.proj.estudo.system.service.impl.Message))") 

Please configure the Message package if it does not fit.

0
source

Source: https://habr.com/ru/post/1266301/


All Articles