Spring 的 AOP 功能是基于 AspectJ 實現(xiàn)的,支持使用注解聲明式定義 AOP 切面。
理解 AOP 概念參閱:《Spring的AOP和動態(tài)代理》
一、概述
Spring 項目使用 AOP 功能需要定義三個部分:切面沼瘫、切點和通知桃熄。
二着茸、AOP 使用
Spring 基于注解配置 AOP 需要啟用 AspectJ 自動代理功能粤策。
基于 Java 配置
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}
基于 XML 配置
<aop:aspectj-autoproxy/>
1. 定義切面
在 Spring 管理的 Bean 類上使用 @Aspect
注解就可以定義一個切面。
@Aspect
@Component
public class DemoAspect {
}
2. 定義切點
在切面類的方法使用 @Pointcut
注解來定義切點误窖,然后在通知注解中使用方法簽名來指定切點叮盘。
切點表達式用來匹配切入的目標類和方法。目標類只能是 Spring 容器管理的類霹俺,切面只能切入 Bean 中的方法柔吼。
@Aspect
@Component
public class DemoAspect {
@Pointcut("execution(* cn.codeartist.spring.aop.aspectj.*.*(..))")
public void pointcut() {
}
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint) {
// do something
}
}
切點表達式也可以在定義通知的時候指定,而不需要使用 @Pointcut
注解丙唧。
@Aspect
@Component
public class DemoAspect {
@Before("execution(* cn.codeartist.spring.aop.aspectj.*.*(..))")
public void doBefore(JoinPoint joinPoint) {
// do something
}
}
3. 定義通知
定義通知的時候需要指定切點愈魏,通知的類型決定了切入的節(jié)點。
前置通知
使用 @Before
注解定義前置通知想际,在方法執(zhí)行前添加操作培漏。
@Aspect
@Component
public class DemoAspect {
@Before("pointcut()")
public void doBefore(JoinPoint joinPoint) {
// do something
}
}
后置通知
使用 @AfterReturning
注解定義后置通知,在方法正常返回時執(zhí)行胡本,方法拋異常不執(zhí)行牌柄。
@Aspect
@Component
public class DemoAspect {
@AfterReturning("pointcut()")
public void doAfterReturning(JoinPoint joinPoint) {
// do something
}
}
環(huán)繞通知
使用 @Around
注解定義環(huán)繞通知,切入方法前后侧甫,相當于攔截器的功能珊佣,可以捕獲異常處理。
環(huán)繞通知的切入點參數(shù)為 ProceedingJoinPoint
披粟,并且需要手動調(diào)用 proceed()
來執(zhí)行切入點方法的邏輯咒锻。
@Aspect
@Component
public class DemoAspect {
@Around("pointcut()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
// do something
Object proceed = joinPoint.proceed();
// do something
return proceed;
}
}
最終通知
使用 @After
注解定義最終通知,在方法退出時執(zhí)行守屉,無論是正常退出還是異常退出惑艇。
@Aspect
@Component
public class DemoAspect {
@After("pointcut()")
public void doAfter(JoinPoint joinPoint) {
// do something
}
}
異常通知
使用 @AfterThrowing
注解定義異常通知,在方法拋出異常時執(zhí)行胸梆。
@Aspect
@Component
public class DemoAspect {
@AfterThrowing("pointcut()")
public void doAfterThrowing(JoinPoint joinPoint) {
// do something
}
}
4. 通過 Advisor 實現(xiàn)
使用 Advisor 能以編程的方式創(chuàng)建切面敦捧,需要實現(xiàn)通知的 API 來定義通知的類型。
比起使用注解定義切點碰镜,這種方式指定切點表達式更靈活兢卵。
@Bean
public AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor() {
AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
advisor.setExpression("execution(* cn.codeartist.spring.aop.aspectj.*.*(..))");
advisor.setAdvice((MethodBeforeAdvice) (method, args, target) -> {
// do something
});
return advisor;
}
三、附錄
1. 常用配置
配置 | 描述 |
---|---|
<aop:aspectj-autoproxy/> |
啟用 AspectJ 自動代理绪颖,通過注解定義切面 |
2. 常用注解
注解 | 描述 |
---|---|
@EnableAspectJAutoProxy |
啟用 AspectJ 自動代理秽荤,通過注解定義切面 |
@Aspect |
定義切面類 |
@Pointcut |
定義切點甜奄,指定切點表達式 |
@Before |
定義前置通知 |
@AfterReturning |
定義后置通知 |
@Around |
定義環(huán)繞通知 |
@After |
定義最終通知 |
@AfterThrowing |
定義異常通知 |
3. 示例代碼
Gitee 倉庫:https://gitee.com/code_artist/spring
項目模塊:spring-aop
示例路徑:cn.codeartist.spring.aop.aspectj
最新文章關(guān)注 CodeArtist 碼匠公眾號。
更多:Spring高效實踐專欄