Spring 当方法在 bean 内部调用时,AOP 不工作
Spring AOP not working, when the method is called internally within a bean
我的应用程序中编码了几个方面。除以下内容外,其他所有内容均有效。
服务接口
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
.
中未命中调试点
更新
我做了一些调查,发现这不起作用,当从 reply
方法调用 send
方法时,如下所示
@Autowire MessageService messageService;
...
messageService.reply(message);
但是如果我调用方法 messageService.send(message)
它工作正常。但是reply方法是在内部调用send方法,难道不应该调用aspect吗?
我不知道我做错了什么。请帮助我。
我想问题出在 @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
如果不合适请调整包装
您 运行 受到 Spring AOP 自我调用的限制。您基本上可以通过使用 AopContext.currentProxy()、将代码重构为不同的 bean 或使用完整的 ApsectJ 编织来绕过它。
请参阅此处的说明和解决方法。
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies
感谢 jst 整理了这些东西。仅供 SO 中的未来开发人员参考,我发布了此问题的完整答案
让我们假设有一个来自 SimplePojo
的 bean
public class SimplePojo implements Pojo {
public void foo() {
this.bar();
}
public void bar() {
...
}
}
当我们调用方法foo()
时,它会重新调用其中的方法bar()
。即使方法 foo()
是从 AOP 代理调用的,bar()
的内部调用也不在 AOP 代理的范围内。
So eventually this makes, if there are any advices attached to the method bar()
to not get invoked
解决方案
使用AopContext.currentProxy()
调用方法。不幸的是,这将逻辑与 AOP 结合在一起。
public void foo() {
((Pojo) AopContext.currentProxy()).bar();
}
参考:
我的应用程序中编码了几个方面。除以下内容外,其他所有内容均有效。
服务接口
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
.
更新
我做了一些调查,发现这不起作用,当从 reply
方法调用 send
方法时,如下所示
@Autowire MessageService messageService;
...
messageService.reply(message);
但是如果我调用方法 messageService.send(message)
它工作正常。但是reply方法是在内部调用send方法,难道不应该调用aspect吗?
我不知道我做错了什么。请帮助我。
我想问题出在 @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
如果不合适请调整包装
您 运行 受到 Spring AOP 自我调用的限制。您基本上可以通过使用 AopContext.currentProxy()、将代码重构为不同的 bean 或使用完整的 ApsectJ 编织来绕过它。
请参阅此处的说明和解决方法。 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies
感谢 jst 整理了这些东西。仅供 SO 中的未来开发人员参考,我发布了此问题的完整答案
让我们假设有一个来自
SimplePojo
的 bean
public class SimplePojo implements Pojo {
public void foo() {
this.bar();
}
public void bar() {
...
}
}
当我们调用方法foo()
时,它会重新调用其中的方法bar()
。即使方法 foo()
是从 AOP 代理调用的,bar()
的内部调用也不在 AOP 代理的范围内。
So eventually this makes, if there are any advices attached to the method
bar()
to not get invoked
解决方案
使用AopContext.currentProxy()
调用方法。不幸的是,这将逻辑与 AOP 结合在一起。
public void foo() {
((Pojo) AopContext.currentProxy()).bar();
}
参考: