繁体   English   中英

Spring JDK动态代理和CGLIB - 实现细节

[英]Spring JDK Dynamic Proxy and CGLIB - implementation details

这个问题的立场,相对于其他关于SO的流行问题

我的问题与“代理内部的自我调用问题”有关,但这不是我的问题。 (我已经找到了解决该问题的一些方法,例如,如此处所述 )。 我还发现基本解释为什么出现这种情况, 在这里

介绍目前的情况

从一开始就开始,我第一次遇到了“自我调用”的问题。 我们正在使用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只是一个普通类,没有实现接口)。 几个小时后,我阅读了关于AOP +的Spring文档以及我在互联网上找到的任何其他内容,以便了解我的类在代理后的样子。 我认为实现我想要的唯一选择是使用代理的其他(第三个?)实现

我的问题是关于这一点的。

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做的事情?

Cglib-proxies的行为与cglib如何工作的方式无关,但与Spring如何使用cglib无关。 Cglib能够委派或子类化调用。 看看实现这个委托的Spring的DynamicAdvisedInterceptor 使用MethodProxy ,它可以改为执行超级方法调用。

Spring定义委托而不是子类,以便最小化使用Cglib或Java代理之间的差异。 这只是一个选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM