1. Aspect(切面):
- 切面由切点和增强组成。
- 切面=切点+增强
2. Pointcut(切点)
为了增强某个业务功能,比如公共日志,比如公共事务,我们需要创建一个标志,代表这个增加。它最终代表是哪些方法可以执行这些增强的功能。我们把这个标志称之为一个切点。
3. Advice(通知/增强):
- 增强的第一层意思是横切逻辑代码(增强逻辑代码)
- 增强的第二层意思是把横切逻辑织入到哪些方法的方法前/后等
3.1 前置通知(before)
作用:用于配置前置通知。指定增强的方法在切入点方法之前执行
属性:
- method:用于指定通知类中的增强方法名称
- ponitcut-ref:用于指定切入点的表达式的引用
- poinitcut:用于指定切入点表达式
执行时间点:切入点方法执行之前执行
3.2 后置通知(afterReturn)
作用:用于配置后置通知。指定增强的方法在切入点方法之后执行
属性:
- method:用于指定通知类中的增强方法名称
- ponitcut-ref:用于指定切入点的表达式的引用
- poinitcut:用于指定切入点表达式
执行时间点:切入点方法正常执行之后。抛出异常就不执行了。
3.3 异常通知(afterThrowing)
作用:用于配置异常通知,方法抛出异常执行
属性:
- method:用于指定通知类中的增强方法名称
- ponitcut-ref:用于指定切入点的表达式的引用
- poinitcut:用于指定切入点表达式
执行时间点:切入点方法执行产生异常后执行。它和后置通知只能执行一个
3.4 最终通知(after)
作用:用于配置最终通知,在方法执行完毕的最后执行
属性:
- method:用于指定通知类中的增强方法名称
- ponitcut-ref:用于指定切入点的表达式的引用
- poinitcut:用于指定切入点表达式
执行时间点:无论切入点方法执行时是否有异常,它都会在其后面执行。
3.5 AOP 环绕通知(around)
作用:用于配置环绕通知。它是 spring 框架为我们提供的一种可以在代码中手动控制增强代码什么时候执行的方式。
属性:
- method:用于指定通知类中的增强方法名称
- ponitcut-ref:用于指定切入点的表达式的引用
- poinitcut:用于指定切入点表达式
注意:通常情况下,环绕通知都是独立使用的
基于注解的AOP编程
<!--添加aop的依赖支持-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
在spring配置文件配上 包扫描(**扫描切面类**)和 Aop注解驱动
<context:component-scan base-package="com.itheima.service,com.itheima.logger"/>
<!--开启注解驱动 支持注解-->
<aop:aspectj-autoproxy/>
/**
* 切面对象=切点+增强逻辑(通知逻辑)
*/
@Component
@Aspect
public class ServiceAop {
/**
* 这就是切点信息 表示对哪些方法感兴趣*/
@Pointcut("execution(* com.itheima.spring.service.impl.*.* (..))")
public void pt1(){
}
@Before("pt1()")
public void beforePrintLog(){
System.out.println("@Before在方法之前执行");
}
@AfterReturning("pt1()")
public void afterReturnPrintLog(){
System.out.println("@AfterReturning,有异常就不执行");
}
@AfterThrowing("pt1()")
public void afterThrowingPrintLog(){
System.out.println("@AfterThrowing在方法抛出异常之后执行");
}
@After("pt1()")
public void afterPrintLog(){
System.out.println("@After 在方法最后执行,不管有没有异常都执行");
}
@Around("pt1()")
public Object aroundPrintLog(ProceedingJoinPoint joinPoint){
Object obj = null;
try {
System.out.println("在方法之前执行");
obj = joinPoint.proceed();//调用方法,这相当于调用被代理类的被增强的方法。有点类似,method.invoked()
System.out.println("在方法之后执行,有异常就不执行");
} catch (Throwable throwable) {
throwable.printStackTrace();
System.out.println("在方法抛出异常之后执行");
} finally {
System.out.println("在方法最后执行,不管有没有异常都执行");
}
return obj;
}
}