簡體   English   中英

為什么在Spring AOP中,對象被包裝到實現接口的JDK代理中?

[英]Why in Spring AOP the object are wrapped into a JDK proxy that implements interfaces?

我正在學習春天,我有跟隨

考慮以下bean定義:

<bean id="clientService" class="com.myapp.service.ClientServiceImpl" />

現在考慮一下它被聲明為切入點*的情況,目標是** clientService bean中的所有方法

還要考慮ClientServiceImpl實現3個接口

現在我知道使用AOP 會對clientService bean進行代理,並且該代理實現所有3個接口。

但是實現所有這三個接口的確切原因是什么?

所以在我看來,存在兩種代理(如果我說的是錯誤的斷言,請糾正我):

  1. JDK代理 :默認使用Spring(是真的嗎?),我有一個接口,用於定義我想要代理的對象的方法。 所以這個接口的具體實現是由代理包裝的。 所以當我在我的對象上調用一個方法時,我在它的代理上調用它。 調用由最終執行方面的方法攔截器識別,然后執行調用的方法。

  2. CGLIB代理:在我看來,代理擴展了包裝對象的實現,增加了額外的邏輯特性

像這樣的東西:

在此輸入圖像描述

所以在我看來Spring使用第一種基於接口實現的代理(是不是?):

在此輸入圖像描述

我認為在AOP中 ,額外的邏輯由方法攔截器的實現來表示(是真的嗎?),標准邏輯由定義在接口中的方法的實現來表示。

但是,如果之前的推理是正確的,我的疑問是:為什么我需要定義這些接口,並且由對象包裝的對象實現這些接口? (我無法理解代理本身是否實現了這些接口)。

為什么? 究竟如何運作?

TNX

但是實現所有這三個接口的確切原因是什么?

如果代理沒有實現所有這些接口,則無法將bean連接到使用該接口的其他bean(您將獲得ClassCastException)。 例如,將該接口的所有bean自動裝配到bean中。 此外,如果代理未實現接口,則getBeanNamesForType內容將無法工作。

所以在我看來,存在兩種代理(如果我說的是錯誤的斷言,請糾正我)

對,那是正確的。 請參閱ScopedProxyMode 默認情況下,Spring不會創建代理。 如果需要包裝bean以添加其他行為(AOP),它只會創建一個代理。 請注意,還有一個基於CGLIB的代理的特例,它使用Objenesis來處理沒有默認構造函數的子類化目標。

CGLIB代理:在我看來,代理擴展了包裝對象的實現,增加了額外的邏輯特性

當您使用基於CGLIB的代理時,bean的構造函數會被調用兩次:一次是動態生成的子類實例化(創建代理),另一次是創建實際的bean(目標)。

我認為在AOP中,額外的邏輯由方法攔截器的實現來表示(是真的嗎?)

代理基本上只是調用需要應用的建議鏈。 該建議未在代理本身中實現。 例如,對@Transactional的建議存在於TransactionAspectSupport中 看一下JdkDynamicAopProxy的源代碼

標准邏輯由接口中定義的方法的實現表示。

假設您正在針對接口進行編程並使用正確的JDK代理。

但是,如果之前的推理是正確的,我的疑問是:為什么我需要定義這些接口,並且由對象包裝的對象實現這些接口? (我無法理解代理本身是否實現了這些接口)。

如果要使用基於接口的代理,則需要使用接口。 只需確保所有bean都實現接口,所有建議的方法都由這些接口定義,並且當一個bean依賴於另一個bean時,使用接口指定該依賴項。 Spring將負責構建代理並確保它實現所有接口。

在您的圖表中,您有“Spring AOP Proxy(this)”。 當您使用任何類型的代理時,您必須非常小心地使用this

  1. 同一類中的調用將不會應用建議,因為這些調用不會通過代理。
  2. 如果你的bean中的一個你通過this一些外部的代碼,你傳遞了AOP通知的目標。 如果某些其他代碼使用該引用,則調用將不會應用AOP建議(再次,您繞過代理)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM