除了其他答案以及您知道AOP代理存在的事实之外,让我仅指向the relevant chapter in Spring documentation,其中提到了您遇到的AOP代理的自调用问题:
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
fun main() {
val factory = ProxyFactory(SimplePojo())
factory.addInterface(Pojo::class.java)
factory.addAdvice(RetryAdvice())
val pojo = factory.proxy as Pojo
// this is a method call on the proxy!
pojo.foo()
}
这里要理解的关键是main(..)
类的Main
方法内部的客户端代码具有对代理的引用。这意味着该对象引用上的方法调用是代理上的调用。结果,代理可以委派给与该特定方法调用相关的所有拦截器(建议)。 但是,一旦调用最终到达目标对象(在这种情况下为引用SimplePojo
),它可能对其自身进行的任何方法调用,例如this.bar()
或{{1} },将针对this.foo()
引用而不是代理进行调用。这具有重要意义。这意味着自调用不会导致与方法调用相关的建议得到执行的机会。
-https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/core.html#aop-understanding-aop-proxies
在下一段中,提出了两种解决方案(或者实际上是三种,但是在这种特殊情况下切换到AspectJ可能会很麻烦):
好的,那该怎么办?最佳方法(在这里宽松地使用术语“最佳”)是重构代码,以免发生自调用。这确实需要您做一些工作,但这是最好的,侵入性最小的方法。下一种方法绝对可怕,我们正要指出这一点,恰恰是因为它是如此可怕。您可以(对我们来说是痛苦的)将类中的逻辑完全绑定到Spring AOP,如以下示例所示:
this
这完全将您的代码耦合到Spring AOP,并且使类本身意识到在AOP上下文中使用它的事实,而AOP却无济于事。创建代理时,还需要一些其他配置,如以下示例所示:
public class SimplePojo implements Pojo {
public void foo() {
// this works,but... gah!
((Pojo) AopContext.currentProxy()).bar();
}
public void bar() {
// some logic...
}
}
class SimplePojo : Pojo {
fun foo() {
// this works,but... gah!
(AopContext.currentProxy() as Pojo).bar()
}
fun bar() {
// some logic...
}
}
最后,必须注意,AspectJ并不是自调用问题,因为它不是基于代理的AOP框架。
-https://docs.spring.io/spring/docs/5.2.3.RELEASE/spring-framework-reference/core.html#aop-understanding-aop-proxies
,
当托管Bean调用另一个托管Bean时,将调用Spring验证。
但是,spring上下文没有意识到同一bean(即,内部bean而非内部bean)中的方法之间的调用,因此@Validation
没有影响。
一个简单的解决方案是将包装器方法从类中移到实用程序方法中,例如:
public static void methodA(MyService myService) {
myService.methodB("");
}
,
Spring中没有注释 @Validation 。我认为您的意思是 @Validated 。
为了验证参数,Spring使用CGLIB创建了一种代理。这是类似于Spring用于事务处理的机制。仅当从另一个类中调用您的类 MyServiceImpl 时,Spring才添加此代码,即,控制流跨越两个类之间的边界。当您从另一个类调用 methodB 时,Spring会添加验证代码。当您从同一类调用它时,Spring不会添加任何代码,因此不会触发任何验证。
本文链接:https://www.f2er.com/2711987.html