簡體   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