AOP 核心概念
| 術語 | 說明 |
| Aspect(切面) | 橫切關注點模組化,包含 Pointcut + Advice |
| Pointcut(切點) | 定義攔截位置,如 execution(* com.cn.study.day6.Test.*(..)) |
| Join Point(連接點) | 程式執行中可插入切面的點,Spring 僅支援方法呼叫 |
| Advice(通知) | 切面要做的事,分 5 種:Before、After、After-returning、After-throwing、Around |
方式一:Spring AOP(XML 配置)
<aop:config>
<aop:aspect id="myAspect" ref="aspect">
<aop:pointcut id="point1" expression="execution(* com.cn.study.day6.Test.*(..))"/>
<aop:before method="before" pointcut-ref="point1"/>
<aop:around method="around" pointcut-ref="point1"/>
</aop:aspect>
</aop:config>
<bean id="aspect" class="com.cn.study.day6.Aspect"/>
切面類
package com.cn.study.day6;
import org.aspectj.lang.ProceedingJoinPoint;
public class Aspect {
public void before() { System.out.println("我是前置通知!"); }
public Object around(ProceedingJoinPoint jp) throws Throwable {
System.out.println("我是環繞通知!方法執行前");
Object obj = jp.proceed(); // 執行目標方法
System.out.println("方法執行之後");
return obj;
}
}
目標類
@Component
public class Test {
public void method1() { System.out.println("業務方法!"); }
}
輸出結果
我是前置通知!
業務方法!
方式二:AspectJ(註解配置)
<aop:aspectj-autoproxy/> <!-- 啟用自動代理 -->
@Component
@Aspect
public class AspectTest {
@Pointcut("execution(* com.cn.study.day7.Test.*(..))")
public void pointCut1() {}
@Before("pointCut1()")
public void before() { System.out.println("我是前置通知!"); }
}
比較與選擇
| 維度 | Spring AOP (XML) | AspectJ (註解) |
| 實現機制 | 運行期動態代理 | 編譯期織入 / 載入期織入 |
| 功能強度 | 僅方法攔截 | 支援欄位、建構子、靜態方法等 |
| 配置風格 | 集中式 XML | 分散式註解,類內聚合 |
| 效能 | 略低(代理開銷) | 較高(無代理) |
實際應用場景
核心優勢:不修改業務代碼即可橫向擴展功能。