其实就是面向特定方法编程
动态代理是面向切面编程最主流的实现,而SpringAOP是Spring框架的高级技术,旨在管理bean对象的过程中,主要通过底层的动态代理机制,对特定的方法进行编程
导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
入门程序
@Slf4j
@Component
@Aspect//AOP类的标志
public class TimeAspect {
@Around("execution(* com.itheima.service.*.*(..))")//切入点表达式
public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
//1.记录开始时间
long begin=System.currentTimeMillis();
//2.调用原始方法运行
Object result=joinPoint.proceed();
//3.记录结束时间,计算方法执行耗时
long end=System.currentTimeMillis();
log.info(joinPoint.getSignature()+"方法执行时间:{}ms",end-begin);
return result;
}
}
连接点:joinPoint,可以被AOP控制的方法(暗含方法执行时的 相关信息)
通知:Advice,指那些重复的逻辑,也就是共性的功能(最终体现为一个方法)
切入点:PointCut,匹配练节点的条件,通知仅仅会在切入点方法执行时被应用
切面:Aspect,描述通知与切入点的对应关系(通知+切入点)
目标对象:Target,通知所应用的对象
通知类型
@Pointcut("execution(* com.itheima.service.*.*(..))")
public void pt(){}
@Around("pt()")//切入点表达式
通知顺序:
当多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行
切入点表达式
@annotation
@Around("@annotation(com.itheima.anno.Log)")
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Log {
}
连接点
在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名,方法名,方法参数等。
对于@Around通知,获取连接点信息只能使用ProceedingJoinPoint
对于其他四种通知,获取连接点信息只能使用JoinPoint,它是 ProceedingJoinPoint的父类型
@Slf4j
@Component
@Aspect//AOP类的标志
public class TimeAspect {
@Pointcut("execution(* com.itheima.service.*.*(..))")
public void pt(){}
@Around("pt()")//切入点表达式
public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {
//获取 目标对象的类名
String className = joinPoint.getTarget().getClass().getName();
//获取 目标方法的方法名
String methodName = joinPoint.getSignature().getName();
//获取 目标方法运行时传入的参数
Object[] args = joinPoint.getArgs();
//放行目标方法执行
Object result = joinPoint.proceed();
//获取 目标方法运行的返回值
log.info("目标方法运行返回值:{}",result);
return null;
}
}