AOP
1. 概念
Aspect 切面,@Aspect
Join point 连接点,例如方法或异常的执行
Advice 通知,切面在连接点处采取的操作
Pointcut 切点,与连接点匹配的谓词
Introduction
Target object
AOP proxy
Weaving
Advice类型
Before advice,在连接点之前执行
After returning advice,在连接点正常完成后执行(比如,方法返回没有抛出异常)
After throwing advice,方法抛出异常
After (finally) advice,无论连接点执行结果是正常还是异常,都执行当前advice
Around advice:
切点使用
execution
within
this
targer
args
@Target
@args
@within
@annotation
&& || !
实例:
execution(public * *(..))
所有public方法
execution(* set*(..))
以set开头的方法
execution(* com.xyz.service.AccountService.*(..))
AccountService接口的所有方法
execution(* com.xyz.service.*.*(..))
com.xyz.service包的所有方法
execution(* com.xyz.service..*.*(..))
within(com.xyz.service.*)
包下面所有连接点
within(com.xyz.service..*)
this(com.xyz.service.AccountService)
target(com.xyz.service.AccountService)
args(java.io.Serializable)
连接点是单参数且运行时是Serializable
@target(org.springframework.transaction.annotation.Transactional)
@within(org.springframework.transaction.annotation.Transactional)
对象有@Transactional注解
@annotation(org.springframework.transaction.annotation.Transactional)
方法有@Transactional注解
bean(tradeService)
2. demo
1.添加依赖并开启AOP:@EnablespectJAutoProxy
2.定义切面
切面类:@Aspect
切点表达式:
@Pointcut("execution(* com.hzk.app.service.*.*(..))")
Advice
@Aspect
@Component
public class TEntityAOP {
@Pointcut("execution(* com.example.demo.mp.service.*.*(..))")
public void pointcut() {}
@Before("pointcut()")
public void beginTransaction(JoinPoint joinPoint) {
System.out.println("@Before start transaction");
}
@AfterReturning(pointcut = "pointcut()", returning = "returnObject")
public void afterReturning(JoinPoint joinPoint, Object returnObject) {
System.out.println("@AfterReturning(transaction commit)");
}
@AfterThrowing("pointcut()")
public void afterThrowing() {
System.out.println("@AfterThrowing(transaction rollback)");
}
@After("pointcut()")
public void afterFinally() {
System.out.println("@After(finally)");
}
}
/*输出
正常:
@Before start transaction
@After(finally)
@AfterReturning(transaction commit)
异常:
@Before start transaction
@After(finally)
@AfterThrowing(transaction rollback)
*/
// @Around("pointcut()")
// public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// try {
// System.out.println("@Around\n" + JSONUtil.toJsonStr(joinPoint));
// Object object = joinPoint.proceed();
// System.out.println("结果:\n" + JSONUtil.toJsonStr(object));
// return object;
// } catch (Throwable e) {
// e.printStackTrace();
// throw e;
// } finally {
// System.out.println("around finally");
// }
// }
3. JoinPoint
方法 | 说明 |
---|---|
getArgs() | 方法参数 |
getThis() | 代理对象 |
getTarget() | 目标对象 |
getSignature() | |
toString |
4. 传递参数给Advice
比如:方法要有两个参数,第一个是Account
@Pointcut("com.xyz.myapp.CommonPointcuts.dataAccessOperation() && args(account,..)")
private void accountDataAccessOperation(Account account) {}
@Before("accountDataAccessOperation(account)")
public void validateAccount(Account account) {
// ...
}
参考
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop