当bean内部调用该方法时,Spring AOP无法正常工作

时间:2015-06-02 13:54:26

标签: java spring spring-boot spring-aop

我在我的应用程序中编写了几个Aspects。所有其他人的工作除以下情况外。

服务界面

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

服务实施

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
@Component
public class NewMessageAspect {
    ...
    @AfterReturning(value = "execution(* com.enbiso.proj.estudo.system.service.impl.MessageServiceImpl.send(..))", 
                    returning = "message")
    public void perform(Message message){
       ...
    }
}

当我尝试执行send方法时,调查点未在perform方面受到影响。

更新

我做了一些调查,发现当send方法从reply方法调用时,这不起作用

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

但是,如果我调用方法messageService.send(message),它可以正常工作。但是由于回复方法在内部调用send方法,它是否也应该调用方面?

我不知道我做错了什么。请帮帮我。

3 个答案:

答案 0 :(得分:10)

感谢您 jst 清除相关内容。仅仅为了SO的未来开发者的信息目的,我发布了这个问题的完整答案

<小时/> 让我们假设有一个来自SimplePojo

的bean
public class SimplePojo implements Pojo {
    public void foo() {
        this.bar();
    }
    public void bar() {
        ...
    }
}

当我们调用方法foo()时,它会重新调用方法bar()。即使从AOP代理调用方法foo(),AOP代理也不会覆盖bar()的内部调用。

Proxy calls

  

因此,如果有任何附加到方法bar()的建议未被调用,那么最终会这样做

<强>解决方案

使用AopContext.currentProxy()调用该方法。不幸的是,它将逻辑与AOP结合在一起。

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

参考:

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

答案 1 :(得分:2)

你在自我调用中遇到了Spring AOP的限制。你基本上可以通过使用AopContext.currentProxy(),重构代码到不同的bean,或使用完整的ApsectJ编织来绕过它。

请参阅此处的说明和解决方法。 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies

答案 2 :(得分:0)

我猜问题是@args条件。

Spring文档说明了以下内容:

@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) 

因此@args的参数必须是类型表达式。所以正确的切入点表达式是

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

或只是

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

如果不合适,请调整Message的套餐。