方式一:AspectJ 註解配置
1. 啟用註解支持
<aop:aspectj-autoproxy/>
2. 切面類
@Aspect
public class SecurityHandler {
@Pointcut("execution(* add*(..))")
private void addMethod() {}
@After("addMethod()")
private void checkSecurity() {
System.out.println("【安全檢查】");
}
}
3. 目標 Bean
<bean id="userManager" class="com.jadyer.annotation.UserManagerImpl"/>
<bean id="securityHandler" class="com.jadyer.annotation.SecurityHandler"/>
方式二:XML 配置(CGLIB 代理)
1. 強制 CGLIB
<aop:config proxy-target-class="true">
<aop:aspect id="securityAspect" ref="securityHandler">
<aop:pointcut id="addMethod" expression="execution(* add*(..))"/>
<aop:before method="checkSecurity" pointcut-ref="addMethod"/>
</aop:aspect>
</aop:config>
2. 切面類無需註解
public class SecurityHandler {
public void checkSecurity(JoinPoint jp) {
System.out.println("方法:" + jp.getSignature().getName());
for (Object arg : jp.getArgs()) System.out.println("參數:" + arg);
System.out.println("【安全檢查】");
}
}
代理機制對比
| 維度 | JDK 動態代理 | CGLIB |
| 前提 | 目標實現接口 | 無需接口,繼承目標類 |
| 原理 | 接口實現 | 字節碼生成子類 |
| 限制 | 無法代理非接口方法 | 不能代理 final 方法/類 |
選型建議
- 業務類均實現接口 → 默認 JDK 代理
- 無接口或需代理具體類方法 → 配置
proxy-target-class="true" 強制 CGLIB
- Spring 會自動判斷:有接口用 JDK,無接口用 CGLIB
切點表達式速查
execution(* add*(..)) // 所有 add 開頭方法
execution(* com.pkg.service.*.*(..)) // service 包所有方法
execution(* *.add*(..)) || execution(* *.del*(..)) // add 或 del 開頭