我在我的应用程序中编写了几个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方法,它是否也应该调用方面?
我不知道我做错了什么。请帮帮我。
答案 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()
的内部调用。
因此,如果有任何附加到方法
bar()
的建议未被调用,那么最终会这样做
<强>解决方案强>
使用AopContext.currentProxy()
调用该方法。不幸的是,它将逻辑与AOP结合在一起。
public void foo() {
((Pojo) AopContext.currentProxy()).bar();
}
参考:
答案 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
的套餐。