《Spring系列》第12章 Aop切面(一) 基础使用

AOP是AspectOrientedProgramming的缩写,用于处理系统中的横切关注点,如事务管理、日志等。文中介绍了AOP的关键概念,包括连接点、切入点、通知、切面、目标对象,以及注解在AOP中的应用,如@Before、@After等。还给出了一个使用SpringAOP的示例,包括定义切面类、增强类以及配置类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Aop基础使用

1.什么是AOP

AOP:Aspect Oriented Programming,中文翻译为”面向切面编程“。
面向切面编程是一种编程范式,它作为OOP面向对象编程的一种补充,用于处理系统中分布于各个模块的横切关注点,
比如事务管理、权限控制、缓存控制、日志打印等等。AOP采取横向抽取机制,取代了传统纵向继承体系的重复性代码

2.专业名词

英文中文描述
Joinpoint连接点类里面可以被增强的方法,这些方法称为连接点
Pointcut切入点所谓切入点是指我们要对哪些Joinpoint进行拦截的定义
Advice通知/增强所谓通知是指拦截到Joinpoint之后所要做的事情就是通知
通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
Advisor通知器其实就是切点和通知的结合
Aspect切面表示Pointcut(切入点)和Advice(增强/通知)的结合
Target目标对象被代理对象

3.注解

注解描述
@EnableAspectJAutoProxy开启自动切面代理,设置需要执行切面的
@Aspect标注增强类
@Before前置通知
@After后置通知
@AfterReturning返回通知
@AfterThrowing异常通知
@Around环绕通知

4.切入点表达式execution

  1. 切入点表达式作用:我们可以通过表达式,来标注对增强类的哪些方法进行增强

  2. 语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称] [(参数列表)] )

    1. 举例 1:对 com.atguigu.dao.BookDao 类里面的 add 进行增强
      execution(* com.atguigu.dao.BookDao.add(…))
    2. 举例 2:对 com.atguigu.dao.BookDao 类里面的所有的方法进行增强
      execution(* com.atguigu.dao.BookDao.* (…))
    3. 举例 3:对 com.atguigu.dao 包里面所有类,类里面所有方法进行增强
      execution(* com.atguigu.dao.. (…))
    4. 举例 4:对 com.atguigu.dao 包里面所有类,类里面的公共方法进行增强

    ​ execution(public * com.atguigu.dao.. (…))

相同的切入点

// 相同切入点抽取 下面避免重复使用
@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
public void pointCur() {
}

@Before(value = "pointCur()")
...

增强类优先级@Order

当有多个增强类类同一个方法进行增强,那么可以通过@Order设置优先级,数字类型值越小优先级越高

@Component
@Aspect
@Order(1)
public class PersonProxy{}

5.示例代码

a> 需要的依赖

// junit
hamcrest-core-1.1.jar
junit-4.12.jar
// Aop
aopalliance-1.0.jar
aspectjrt-1.9.6.jar
aspectjweaver-1.9.7.jar
cglib-3.2.0.jar
commons-logging-1.1.1.jar
spring-aop-5.1.5.RELEASE.jar
spring-aspects-5.3.13.jar
// Spring核心注解
spring-beans-5.1.5.RELEASE.jar
spring-context-5.1.5.RELEASE.jar
spring-core-5.1.5.RELEASE.jar
spring-expression-5.1.5.RELEASE.jar

b> 切面类

// 定义一个方法,执行切面方法
@Component
public class MathCalculator {

    public int div(int i, int j) {
        System.out.println("执行 div 方法");
        return i / j;
    }
}

c> 增强类

package com.jianan.spring5.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;

@Component
@Aspect
public class LogAspect {

    @Pointcut(value = "execution(public int com.jianan.spring5.aop.MathCalculator.*(..))")
    public void pointCur() {
    }

    @Before(value = "pointCur()")
    public void before(JoinPoint joinPoint) {
        // 参数
        Object[] args = joinPoint.getArgs();
        // 切面方法信息
        Signature signature = joinPoint.getSignature();
        // 切面方法名
        String name = signature.getName();
        // 切面方法权限修饰符
        int modifiers = signature.getModifiers();
        // 切面类Class
        Class declaringType = signature.getDeclaringType();
        // 切面包名+类名
        String declaringTypeName = signature.getDeclaringTypeName();
        System.out.println("----before-----");
    }

    @After(value = "pointCur()")
    public void after(JoinPoint joinPoint) {
        System.out.println("----after----");
    }

    @AfterReturning(value = "pointCur()", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("-----afterReturning------- 返回值:" + result);
    }

    @AfterThrowing(value = "pointCur()", throwing = "e")
    public void afterThrowing(JoinPoint joinPoint, Exception e) {
        System.out.println("------joinPoint------- 异常:" + e.getMessage());
    }

    @Around(value = "pointCur()")
    public Object around(ProceedingJoinPoint joinPoint) {
        System.out.println("------around------");
        Object result = null;
        try {
            Object[] args = joinPoint.getArgs();
            result = joinPoint.proceed(args);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }
}

b> 配置类

package com.jianan.spring5.aop;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@Configuration
@ComponentScan(basePackages = "com.jianan")
public class AspectConfig {

}

d> 测试

	@Test
    public void m1() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectConfig.class);
        MathCalculator mathCalculator = context.getBean(MathCalculator.class);
        int ans = mathCalculator.div(10, 5);
        System.out.println("结果:" + ans);
    }

e> 结果

------around------
----before-----
执行 div 方法
----after----
-----afterReturning------- 返回值:2
结果:2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为人师表好少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值