Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring AOP not working, when the method is called internally within a bean

I have several Aspects coded in my application. All others works 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 is not getting hit in the aspect perform.

UPDATE

I did some investigations and found that this doesn't work, when the send method is invoked from the reply method as below

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

But if I call the method messageService.send(message) it works fine. But as reply method is calling send method internally, shouldn't it also invoke the aspect?

I have no idea what i have done wrong. Please help me.

like image 218
Faraj Farook Avatar asked Jun 02 '15 13:06

Faraj Farook


People also ask

How AOP works internally in spring?

Spring AOP is proxy-based. Spring uses either JDK proxies (preferred wheneven the proxied target implements at least one interface) or CGLIB proxies (if the target object does not implement any interfaces) to create the proxy for a given target bean.

Which advice is invoked every single time in method calls?

Run advice after the method execution, regardless of its outcome. Run advice after the method execution, only if the method completes successfully. Run advice after the method execution, only if the method exits by throwing an exception. Run advice before and after the advised method is invoked.

What is the difference between execution and within in Spring AOP?

execution – for matching method execution join points. This is the most widely used PCD. within – for matching methods of classes within certain types e.g. classes within a package. @within – for matching to join points within types (target object class) that have the given annotation.


1 Answers

Thank you jst for clearing the things up. Just for the information purposes for the future developer in SO, I'm posting the full answer to this question


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

When we call the method foo(), it reinvokes the method bar() inside it. Even thought the method foo() is invoked from the AOP Proxy, the internal invocation of the bar() is not covered by the AOP Proxy.

Proxy calls

So eventually this makes, if there are any advices attached to the method bar() to not get invoked

Solution

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

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

Reference:

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

like image 62
Faraj Farook Avatar answered Sep 18 '22 10:09

Faraj Farook