首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 事務管理與 AOP 框架內幕:代理模式、CGLIB 與 Introduction 實戰

     編輯:Java 相關知識

Spring 事務管理核心

Spring 透過 AOP 為普通 Java 類(POJO)提供聲明式事務管理,避免 EJB 重量級容器,適用於大多數 Web 應用。雖不支援跨資源管理器分佈式事務(JTA 需額外配置),但單數據源場景足夠。

AOP 實現兩大引擎

  • JDK 動態代理:目標類實現介面時使用,生成實現同樣介面的代理類。
  • CGLIB:目標類未實現介面時,動態生成子類覆寫非 final 方法。

Spring 自動選擇,亦可強制 proxy-target-class="true" 全用 CGLIB。

四種 Advice 類型

類型切入點返回值異常行為典型用途
Around方法執行前後可攔截/修改可阻止繼續執行事務邊界、性能監控、緩存
Before方法執行前無拋出異常則阻止目標方法權限檢查、日誌記錄
After方法執行後無不影響目標方法返回資源清理、統計
Introduction類級別動態新增方法/介面無混入審計字段、實現新介面

Introduction 實戰:動態為業務對象添加審計時間

1. 定義審計介面

package com.osiris.springaop.advices.intruduction;
import java.util.Date;
public interface IAuditable {
    void setLastModifiedDate(Date date);
    Date getLastModifiedDate();
}

2. 實現 IntroductionInterceptor

package com.osiris.springaop.advices.intruduction;
import java.util.Date;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.IntroductionInterceptor;

public class AuditableMixin implements IAuditable, IntroductionInterceptor {
    private Date lastModifiedDate;
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (implementsInterface(mi.getMethod().getDeclaringClass())) {
            return mi.getMethod().invoke(this, mi.getArguments()); // 委派給 IAuditable 方法
        }
        return mi.proceed(); // 委派給目標業務方法
    }
    public Date getLastModifiedDate() { return lastModifiedDate; }
    public void setLastModifiedDate(Date date) { lastModifiedDate = date; }
    public boolean implementsInterface(Class cls) {
        return IAuditable.class.isAssignableFrom(cls); // 注意:原文邏輯有誤,應為 cls.isAssignableFrom(IAuditable.class) 或 IAuditable.class.isAssignableFrom(cls)
    }
}

3. 業務介面與實現

public interface BookService {
    String OrderBook(String userName, String bookName);
    String OrderComputerMagazine(String userName, String bookName);
}
public class BookServiceImpl implements BookService {
    public String OrderBook(String name, String bookName) {
        return "訂購" + bookName + "成功";
    }
    public String OrderComputerMagazine(String userName, String bookName) {
        return "訂購" + bookName + "成功";
    }
}

4. Spring 配置(概念示意)

<bean id="bookService" class="com.osiris.springaop.BookServiceImpl"/>
<bean id="auditableMixin" class="com.osiris.springaop.advices.intruduction.AuditableMixin"/>
<aop:config>
  <aop:advisor advice-ref="auditableMixin"
    pointcut="bean(bookService)"/> <!-- Introduction 需特殊配置,通常用 ProxyFactoryBean -->
</aop:config>

5. 運行時效果

BookService bookService = (BookService) context.getBean("bookService");
bookService.OrderBook("user", "Professional C#");
// 強制轉型調用混入方法
IAuditable auditable = (IAuditable) bookService;
auditable.setLastModifiedDate(new Date());
System.out.println("訂購時間為 " + auditable.getLastModifiedDate());

輸出:

訂購Professional C#成功 訂購時間為Mon Nov 07 11:35:20 CST 2005

關鍵總結

  1. Introduction 允許運行時為現有 Bean 動態實現新介面,無需修改原類代碼。
  2. 底層原理類似 C++ 虛函數表:代理內部維護多個介面的方法分發表。
  3. 性能代價:動態分發比直接調用慢,慎用於高頻熱點路徑。
  4. 事務管理本質是 Around Advice:開啟事務 → 執行目標方法 → 提交/回滾。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved