我的问题与代理人内部的自我调用问题有关,但这不是我的问题。 (我已经找到了一些解决该问题的方法,例如,here)。我还找到了为什么会发生这种情况的基本解释,here
从一开始,我第一次遇到了自我调用问题"工作中。我们正在使用Spring Boot,我们有一些服务需要审计一些数据(使用AspectJ),以及PreAuthorize该方法。该方法本身必须返回一些内容,但审核其他内容。所以现在我们的服务看起来像:
class Service {
Service self;
public Service() {
// I don't like this because it makes my Service to be aware of the fact that it's a proxy. I just wanted my class to be a pojo with annotations
self = AopContext.currentProxy();
}
@Audit
public CustomClassContainingTheValuesToAudit getValuesFromServer() {
CustomClassContainingTheValuesToAudit c;
try {
Object answer = self.doGetValuesFromServer();
c = ... ; // create what to audit based on the answer
} catch (...) {
// log the fact that you didn't have enough privileges to run doGetValuesFromServer()
// create c based on the exception I got
c = ...;
}
return c; // object to be audited
}
@PreAuthorize(.....)
public Object doGetValuesFromServer() {
.........
}
}
我主要担心如上所述让AspectJ + PreAuthorize协同工作,但不要让我的班级意识到它被代理的事实。 所以我想确切地了解我在代理类型方面的选择是什么。我发现Spring带有两种代理:JDK Dynamic Proxies和CGLIB代理。事实证明我们正在使用CGLIB代理,我们将Spring配置为使用CGLIB(无论如何,现在Service只是一个普通的类,并没有实现一个接口)。几个小时后,我在Spring documentation on AOP +读到了我在互联网上找到的任何其他东西,以便了解我的课程在被代理后的样子。我认为实现我想要的唯一选择是使用代理
的其他(第三个?)实现1)根据我对代码现在的描述,我会做些什么来避免从上下文中获取bean?我不想在两个类中打破每个服务,以避免自我调用问题。我想要一种方法来使aspectJ和PreAuthorize按照描述工作。 2)我不明白CGLIB实现代理的原因。 所以,让我说我的班级服务
class Service {
public void methodA(){
// do methodA stuff
// call method b
methodB();
}
public void methodB(){
// do methodB stuff
}
}
然后GCLIB会生成一个类:
class Service$CGLIB extends Service {
// it's only extending my class to make it compatible with the variable where i'm storing/autowiring the proxy
Service privateField; // but it's actually using a decorator pattern, just like JDK Dynamic Proxies do
public void methodA() {
// do any magic before
privateField.a();
// any magic after the call
}
public void methodB() {
// magic
privateField.b();
// some more magic
}
}
为什么CGLIB只调用super.a()和super.b()?为什么需要装饰而不是委托呢?我认为我需要的是代理委托给super。我是这样做的,因为多态性,我在自我调用方面没有任何问题。是否有代理的实现可以完成我期望CGLIB做的事情?
答案 0 :(得分:0)
Cglib-proxies的行为与cglib的工作方式无关,但与Spring如何使用cglib无关。 Cglib能够委派或子类化调用。看一下实现这个委托的Spring DynamicAdvisedInterceptor
。使用MethodProxy
,它可以改为执行超级方法调用。
Spring定义委托而不是子类,以便最小化使用Cglib或Java代理之间的差异。这只是一个选择。