目录
概述
快速入门
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
编写AOP程序
@Slf4j
@Aspect
@Component
public class TimeAspect {
@Around("execution(* com.itheima.service.*.*(..))")//切入点表达式.后面会详解
public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
//记录开始时间
long begin = System.currentTimeMillis();
//调用原始方法
Object result = joinPoint.proceed();
//记录结束时间
long end = System.currentTimeMillis();
log.info(joinPoint.getSignature()+"方法执行耗时{}ms",end-begin) ;
return result;
}
}
此时运行该项目,指定包下的每个方法运行时都会自动记录运行时间
核心概念
连接点:JoinPoint,可以被AOP控制的方法
通知:Advice,指重复的逻辑,即要实现的共性功能(做什么)
切入点:PointCut,匹配连接点的条件,通知仅仅会在切入点方法执行时被应用(给谁做)
切面:Aspect通知与切入点的对应关系(通知+切入点)
目标对象:Target,通知所应用的对象
AOP进阶--通知类型--五种演示
环绕通知很特殊,需要手动调用原始方法执行,因为AOP并不知道你想让他什么时候执行原方法
AOP进阶--抽取切入点
AOP进阶--通知顺序
AOP进阶--切入点表达式
一般来说我们采用第二种表达式来选择切入点:
第一步:标识@annotation类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyLog {
}
第二步: 配置切面类
@Slf4j
@Aspect
@Component
public class MyAspect1 {
@Pointcut("@annotation(com.itheima.aop.MyLog)")
private void pt(){}
@Before("pt()")
public void before(){
log.info("---my aspect---before---");
}
}
第三步:使用注解控制AOP生效范围
@MyLog
@Override
public List<Dept> list(){
return deptMapper.list();
}
@MyLog
@Override
public void delete(int id){
deptMapper.delete(id);
empMapper.delete(id);
}
AOP进阶--连接点
可以理解为: AOP生效的方法(实际上即AOP的目标对象)
@Before("pt()")
public void before(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("---my aspect---before---");
/*获取目标对象类名*/
String className = joinPoint.getTarget().getClass().getName();
/*获取目标方法的方法名*/
String methodName = joinPoint.getSignature().getName();
/*获取方法运行时传入的参数*/
Object[] args = joinPoint.getArgs();
/*放行目标方法*/
Object result = joinPoint.proceed();
/*获取目标方法返回值*/
log.info("返回值为{}",result);
}