Spring事務管理與AOP代理的原理,預設的單例物件和代理物件銷燬的時機

菜鸟的奋斗之路發表於2024-10-10

Spring的事務管理是使用AOP(面向切面程式設計)代理的原理來實現的。

Spring事務管理與AOP代理原理

  1. AOP代理的作用:

    • 在Spring中,AOP代理用於在目標物件的方法執行前後注入自定義的邏輯,這些邏輯通常與業務邏輯無關,但需要在業務邏輯執行時同步執行,如事務管理、日誌記錄、效能檢測等。
    • 透過AOP代理,可以將這些橫切關注點(cross-cutting concerns)從核心業務邏輯中分離出來,使得業務邏輯更加清晰和模組化。
  2. AOP代理的實現方式:

    • Spring AOP主要使用了兩種動態代理方式:JDK動態代理和CGLIB動態代理。
    • 如果目標物件實現介面,Spring預設使用JDK動態代理。JDK動態代理是基於介面的代理,透過反射機制生成一個實現了目標物件介面的代理類。
    • 如果目標物件沒有實現介面,Spring使用CGLIB動態代理。CGLIB代理是基於類代理,透過操作位元組碼生成目標物件的子類,並重寫其中的方法。
  3. 事務管理的實現:

    • 當為某個Bean配置事務管理時,Spring會為其建立一個代理物件。
    • 當呼叫該Bean的某個方法時,實際上是呼叫生成的代理物件的方法。
    • 代理物件會在方法執行前後注入事務管理的邏輯,如開啟事務、提交事務、回滾事務等。

為什麼要建立代理物件?

  1. 實現AOP功能:代理物件是實現AOP功能的關鍵。透過代理物件,可以在目標物件的方法執行前後注入自定義的邏輯,從而實現橫切關注點的分離。
  2. 控制目標物件的訪問:代理物件還可以提供額外的訪問控制,如許可權控制、引數校驗等。

Spring的單例模式

  1. 預設單例模式:

    • Spring容器預設會將所有的Bean都設定為單例模式。這意味著在Spring容器的整個生命週期中,每個Bean只會被建立一次,並且每次獲取該Bean時都會返回同一個例項。
    • 單例模式有助於減少記憶體佔用和提高效能,因為多個元件可以共享同一個Bean例項。
  2. 如何設定單例模式:

    • 在Spring中,可以透過註解(如@Component@Bean等)或XML配置來顯式地設定Bean的作用域為單例。但通常情況下,無需額外配置,因為單例模式是Spring的預設行為。
  3. 單例模式的注意事項:

    • 在併發環境下,單例模式可能會引發執行緒安全問題。因此,在Bean類中需要採用同步機制或使用執行緒安全的物件來確保執行緒安全。
    • 單例模式可能會增加耦合性,因為多個元件共享同一個Bean例項。因此,在應用設計中需要慎重考慮是否真正需要使用單例模式。

Spring的事務管理是透過AOP代理來實現的,代理物件的建立是為了實現AOP功能和控制目標物件的訪問。同時,Spring容器預設會將所有的Bean設定為單例模式,以提高效能和減少記憶體佔用。

重點理解:在Spring框架中,當為某個Bean配置事務管理時,Spring確實會為其建立一個代理物件以及目標物件。這兩個物件的銷燬時機取決於Spring容器的生命週期管理和Bean的作用域設定。

代理物件的銷燬時機

代理物件的銷燬時機通常與Spring容器的生命週期相關,具體取決於代理物件的作用域設定:

  1. 單例作用域(Singleton):

    • 當代理物件被配置為單例作用域時,它的生命週期與Spring容器的生命週期一致。
    • 在Spring容器關閉時,會觸發代理物件的銷燬方法。此時,Spring容器會呼叫代理物件實現的DisposableBean介面的destroy方法(如果代理物件實現了該介面),或者呼叫在配置檔案中透過destroy-method屬性指定的銷燬方法。
  2. 原型作用域(Prototype):

    • 當代理物件被配置為原型作用域時,每次獲取代理物件時都會建立一個新的例項。
    • 代理物件例項的銷燬不是由Spring容器管理的,而是由使用它們的程式碼來管理的。通常,這些例項會在不再被使用時被垃圾回收器回收。
  3. 其他作用域:

    • 對於會話作用域(Session Scope)、執行緒作用域(Thread Scope)和請求作用域(Request Scope)的代理物件,它們的生命週期分別與會話、執行緒和請求的生命週期一致。
    • 當會話結束、執行緒結束或請求結束時,會觸發代理物件的銷燬方法。

目標物件的銷燬時機

目標物件的銷燬時機也取決於其作用域設定,但通常與代理物件的銷燬時機相關聯:

  1. 如果目標物件也是單例作用域:

    • 當Spring容器關閉時,會同時銷燬代理物件和目標物件。
  2. 如果目標物件是原型作用域或其他作用域:

    • 目標物件的銷燬時機將根據其作用域設定來確定,可能與代理物件的銷燬時機不同。
    • 例如,如果目標物件是原型作用域,則每次獲取目標物件時都會建立一個新的例項,並且這些例項的銷燬將由使用它們的程式碼來管理。

需要注意的是,Spring容器的關閉通常發生在應用程式關閉時。在Spring Boot應用中,Spring容器會在應用程式退出時自動關閉。如果希望在應用程式執行期間手動關閉Spring容器,可以使用ConfigurableApplicationContext介面的close方法來關閉容器。

所以代理物件和目標物件的銷燬時機取決於Spring容器的生命週期管理和Bean的作用域設定。在應用程式關閉時、目標物件或代理物件的作用域結束時,或者代理物件例項不再被使用時,這些物件可能會被銷燬。

相關文章