springAOP - 教程

AOP基础

AOP:Aspect Oriented Programming(面向切面编程、面向方面编程),面向切面编程就是面向特定方法编程。

AOP的优势主要体现在以下四个方面:

  • 减少重复代码:不需要在业务方法中定义大量的重复性的代码,只需要将重复性的代码抽取到AOP程序中即可。
  • 代码无侵入:在基于AOP实现这些业务功能时,对原有的业务代码是没有任何侵入的,不需要修改任何的业务代码。
  • 提高开发效率
  • 维护方便

AOP是一种思想,而在Spring框架中,对这种思想进行了实现,那我们要学习的就是Spring AOP。

AOP核心概念

AOP进阶

通知类型

Spring AOP 通知类型

@Around

环绕通知,此注解标注的通知方法在目标方法前、后都被执行

@Before

前置通知,此注解标注的通知方法在目标方法前被执行

@After

后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

@AfterReturning

返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

@AfterThrowing

异常后通知,此注解标注的通知方法发生异常后执行

Spring提供了@PointCut注解,该注解的作用是将公共的切入点表达式抽取出来,需要用到时引用该切入点表达式即可。

@Slf4j
@Component
@Aspect
public class MyAspect1 {
//切入点方法(公共的切入点表达式)
@Pointcut("execution(* com.itheima.service.*.*(..))")
private void pt(){}
//前置通知(引用切入点)
@Before("pt()")
public void before(JoinPoint joinPoint){
log.info("before ...");
}
}

通知顺序

  • 当有多个切面的切入点都匹配到了目标方法,目标方法运行时,多个通知方法都会被执行。
  • 执行顺序:
    • 不同切面类中,默认按照切面类的类名字母排序:
      • 目标方法前的通知方法:字母排名靠前的先执行
      • 目标方法后的通知方法:字母排名靠前的后执行
    • 用 @Order (数字) 加在切面类上来控制顺序
      • 目标方法前的通知方法:数字小的先执行
      • 目标方法后的通知方法:数字小的后执行

切入点表达式

一、execution

execution主要根据方法的返回值、包名、类名、方法名、方法参数等信息来匹配,语法为:

execution(访问修饰符? 返回值 包名.类名.?方法名(方法参数) throws 异常?)

其中带?的表示可以省略的部分

  • 访问修饰符:可省略(比如: public、protected)

  • 包名.类名: 可省略

  • throws 异常:可省略(注意是方法上声明抛出的异常,不是实际抛出的异常)

@Before("execution(void com.itheima.service.impl.DeptServiceImpl.delete(java.lang.Integer))")

可以使用通配符描述切入点

  • * :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分
  • .. :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

切入点表达式的语法规则:

  1. 方法的访问修饰符可以省略

  2. 返回值可以使用*号代替(任意返回值类型)

  3. 包名可以使用*号代替,代表任意包(一层包使用一个*

  4. 使用..配置包名,标识此包以及此包下的所有子包

  5. 类名可以使用*号代替,标识任意类

  6. 方法名可以使用*号代替,表示任意方法

  7. 可以使用 * 配置参数,一个任意类型的参数

  8. 可以使用.. 配置参数,任意个任意类型的参数

根据业务需要,可以使用 且(&&)、或(||)、非(!) 来组合比较复杂的切入点表达式。

二、@annotation

实现步骤:

  1. 编写自定义注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface LogOperation{
    }

  2. 在业务类要做为连接点的方法上添加自定义注解

    @Slf4j
    @Service
    public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;
    @Override
    @LogOperation //自定义注解(表示:当前方法属于目标方法)
    public List list() {
    List deptList = deptMapper.list();
    //模拟异常
    //int num = 10/0;
    return deptList;
    }

 3. 在切面类上

@Slf4j
@Component
@Aspect
public class MyAspect6 {
//针对list方法、delete方法进行前置通知和后置通知
//前置通知
@Before("@annotation(com.itheima.anno.LogOperation)")
public void before(){
log.info("MyAspect6 -> before ...");
}
posted @ 2025-08-14 22:55  wzzkaifa  阅读(22)  评论(0)    收藏  举报