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

Spring 2.0 整合 AspectJ 實戰:LTW 織入與 IoC 容器管理切面的雙重奏

     編輯:Java 相關知識

三種織入方式對比

方式時機工具/機制
編譯期織入javac 階段AspectJ 編譯器
類加載期織入 (LTW)類載入 JVM 時特殊類加載器 + -javaagent
運行期織入運行時動態代理CGLib / JDK Proxy

AspectJ 採用前兩種,屬語言級 AOP,功能完備。Spring 2.0 引入 AspectJ 切點表達式解析,但本文聚焦**深度整合**:AspectJ 負責織入,Spring IoC 管理切面實例與依賴注入。

LTW 環境搭建

1. JVM 參數 -javaagent

  • Eclipse:Run Configurations → Arguments → VM arguments 添加
    -javaagent:D:\path\to\aspectjweaver.jar
  • Tomcat:catalina.bat 頭部添加
    set JAVA_OPTS=-javaagent:D:\path\to\aspectjweaver.jar

2. META-INF/aop.xml 織入配置

<aspectj>
  <aspects>
    <aspect name="com.baobaotao.aspectj.TestAspectJ"/>
  </aspects>
  <weaver>
    <include within="com.baobaotao..*"/>
  </weaver>
</aspectj>

include 限定織入範圍,避免全量掃描影響啟動性能。

切面類與目標類編寫

目標類

public class Waitress {
    private String name;
    public void serveTo(String client) {
        System.out.println(name + " serves to " + client + "...");
    }
    // getter/setter
}

AspectJ 切面類

public aspect TestAspectj {
    private pointcut traceServeTo() : execution(* serveTo(..));
    before(): traceServeTo() {
        System.out.println(message); // 禮貌用語
    }
    private String message;
    public void setMessage(String message) { this.message = message; }
}

Spring IoC 管理切面實例

<bean id="aspectj" class="com.baobaotao.TestAspectj" factory-method="aspectOf">
  <property name="message" value="How are you!"/>
</bean>
<bean id="waitress" class="com.baobaotao.Waitress">
  <property name="name" value="Katty"/>
</bean>

關鍵:factory-method="aspectOf" 讓 Spring 從 AspectJ 獲取單例切面實例,而非自行創建。

調整 aop.xml

<aspectj>
  <aspects>
    <aspect name="com.baobaotao.TestAspectj"/>
  </aspects>
  <weaver options="-showWeaveInfo -XmessageHandlerClass:org.springframework.aop.aspectj.AspectJWeaverMessageHandler">
    <include within="com.baobaotao..*"/>
  </weaver>
</aspectj>

測試驗證

ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
Waitress waitress = (Waitress) ctx.getBean("waitress");
waitress.serveTo("Johnson");

輸出:How are you! Katty serves to Johnson... —— 切面織入生效,禮貌用語從 Spring 注入。

進階:Spring 管理容器外對象(@Configurable)

利用 org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect(位於 spring-aspects.jar)織入標注 @Configurable 的類,實現 new DomainObject() 也能享受 IoC 依賴注入。

領域對象

@Configurable
public class Thread implements Serializable {
    private String title;
    private Topic topic; // 自動注入
    // getter/setter/toString
}

@Configurable
public class Topic implements Serializable {
    private String title;
    private String content;
    // getter/setter/toString
}

aop.xml 限定範圍

<aspectj>
  <weaver options="...">
    <include within="com.baobaotao.configure..*"/>
  </weaver>
</aspectj>

Spring 配置

<aop:spring-configured/> <!-- 等價於聲明 AnnotationBeanConfigurerAspect -->
<bean class="com.baobaotao.configure.Topic" scope="prototype">
  <property name="title" value="測試帖子"/>
  <property name="content" value="測試內容"/>
</bean>
<bean class="com.baobaotao.configure.Thread" scope="prototype">
  <property name="title" value="測試的主題"/>
  <property name="topic" ref="com.baobaotao.configure.Topic"/>
</bean>

測試

Thread thread = new Thread(); // 普通 new
System.out.println(thread);   // 輸出 Spring 配置的值

日志顯示 AspectJ 對 Thread、Topic 構造器織入 afterReturning 增強,從容器獲取 Bean 注入字段。

關鍵機制總結

  • AnnotationBeanConfigurerAspect 為每 ClassLoader 單例,實現 BeanFactoryAware
  • 通過反射獲取目標類全限定名作為 Bean 名(可用 @Configurable("customName") 覆蓋)
  • Spring aop 命名空間提供 <aop:spring-configured/> 簡化配置

選型建議

Spring 2.0 提供 @AspectJ、Schema、AspectJ 原生三種 AOP 風格。**原則:從項目實際需求出發,選最簡單、最合適的方式。** 需要完整 AOP 能力(構造器切面、字段切面、靜態初始化切面)時,AspectJ + Spring IoC 是最強組合。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved