AOP之环绕通知@Around
@Around是Spring AOP中环绕通知的注解,作用是定义一个切面,用于在目标方法之前和之后执行一些额外的逻辑。
另外,@Around也是自定义注解时需要使用的注解。
@Around 方法必须接收一个 ProceedingJoinPoint 参数,以便通过 proceed() 调用目标方法。
环绕通知定义
@Aspect
@Component
public class LogExectionTimeAspect {
/**
* 环绕通知的具体业务逻辑
* @param joinPoint
* @return
* @throws Throwable
*/
// 环绕通知注解 @Around
@Around("execution(* com.example.service.*.*(..))")
public Object logExectionTime(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("触发前: "+ System.currentTimeMillis());
/**
* proceed 函数用于调用执行逻辑
* 是环绕通知(@Around)的关键方法,
* 更多的作用是在环绕通知中根据某些逻辑阻止方法执行或者修改方法的参数和返回值
* 返回值便是原函数返回值
*/
Object proceed = joinPoint.proceed(); // 执行目标方法
// 获取目标参数示例
// Object[] args = joinPoint.getArgs(); // 获取目标方法的参数
// do somthing
// 使用修改后的参数
// Object result = joinPoint.proceed(args);
joinPoint.getSignature(); // 该函数可以获取方法相关信息
System.out.println("触发后: "+ System.currentTimeMillis());
return proceed;
}
}
自定义注解
/**
* 自定义注解起始
* 1. 创建自定义注解,即该接口
* 2. 实现注解功能
*/
@Target(ElementType.METHOD) // 可以用于方法上
@Retention(RetentionPolicy.RUNTIME) // 注解在运行时可用
public @interface LogExectionTime {
}
自定义注解实现:
/**
* 自定义注解实现类
*/
@Aspect
@Component
public class LogExectionTimeAspect {
/**
* 环绕通知的具体业务逻辑
* @param joinPoint
* @return
* @throws Throwable
*/
// 环绕通知注解 @Around
@Around("@annotation(com.example.demo.aop.LogExectionTime)") // 此处路径就是创建的@interface的路径
public Object logExectionTime(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("触发前: "+ System.currentTimeMillis());
// do something
// ...
Object proceed = joinPoint.proceed(); // 执行目标方法
joinPoint.getSignature();
System.out.println("触发后: "+ System.currentTimeMillis());
return proceed;
}
}
说明
execution用于指定监听范围。execution可以有很多写法,下面会介绍几种。
"execution(public * com.example.demo.service.impl.AccountServiceImpl.aopBeforeMsg(...))"
"execution(* com.example.demo.service.impl.AccountServiceImpl.aopBeforeMsg(...))"
以上两种写法都表明监听com.example.demo.service.impl.AccountServiceImpl类下的aopBeforeMsg函数。
"execution(public * com.example.demo.service.impl.AccountServiceImpl.*(...))"
以上表明监听AccountServiceImpl类下的所有函数。
"execution(public * com.example.demo.service.impl.AccountServiceImpl.get*(...))"
以上写法表明监听AccountServiceImpl类下所有get开头函数。
"execution(public * com.example.demo.service.impl.AccountServiceImpl.get*(...)) || || execution(* com.example.service.OrderService.get*(...)) "
以上写法表示监听AccountServiceImpl类与OrderService类中get开头的函数。
"execution(* com.example.service...*(...))"
以上写法表示监听service包下的所有函数。
注意点
@Around也只能监听public和protected修饰的函数,并且实例必须是依赖Spring管理。