Spring AOP使用

Spring AOP是什么?

AOP(面向切面编程):将那些与业务无关,却为业务模块所共同调用的逻辑(例如事务处理、日志管理、权限控制等)封装抽取成一个可重用的模块,这个模块被命名为"切面"(Aspect),便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可拓展性和可维护性;

在Spring AOP中,切面由切点(Pointcut)和通知(Advice)组成。切点是一个表达式,用于匹配哪些方法需要被横切,通知是在切点位置执行的代码,表示横切逻辑。

++切点表达式配置语法:++

execution(修饰符 返回值 包名称.类名称.方法名称(参数列表))

execution(public void com.apesource.service.ServiceImp.findAll())

  1. 修饰符可以省略代表任意 execution(返回值 包名称.类名称.方法名称(参数列表))
  2. 返回值可以使用"*"代表任意 execution(* 包名称.类名称.方法名称(参数列表))
  3. 包名可以使用"*"代表任意名称 execution(* *.*.*.类名称.方法名称(参数列表))
  4. 包名可以使用".."代表任意个数 execution(* *...类名称.方法名称(参数列表))
  5. 类名与方法名可以使用"*"代表任意 execution(* *...*.*(参数列表))
  6. 参数列表可以使用".."代表任意个数任意类型 execution(* *...*.*(..))

如果有参数 int======>int String===>java.lang.String

++Spring AOP提供了几种常见的通知类型,包括:++

  • 前置通知(Before):在方法执行前执行的逻辑
  • 后置通知(After):在方法执行后执行的逻辑
  • 返回通知(After-returning):在方法成功返回后执行的逻辑
  • 异常通知(After-throwing):在方法抛出异常后执行的逻辑
  • 环绕通知(Around):在方法执行前后都可以执行的逻辑,可以控制目标方法的执行流程

Spring AOP 基于动态代理实现:

  • 如果被代理的对象,已经实现某个接口,则 Spring AOP 会使用 JDK Proxy(反射),基于接口的方式,创建代理对象;
  • 如果被代理的对象,没有实现某个接口, Spring AOP 会使用 Cglib,基于继承的方式,生成一个被代理对象的子类来作为代理;

Spring AOP可以通过注解或XML配置的方式来定义切点和通知,并且可以与Spring的IOC容器无缝集成,使得切面和目标对象的创建和管理变得更加简单。

1⃣️XML

1.添加依赖:

java 复制代码
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.28</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

2.创建切面类:

java 复制代码
public class LoggerUtil {
    //前置通知
    public void beforeMethod(){
        System.out.println("前置通知=====>"+new Date());
    }
    //返回通知
    public void afterRrturnMethod(){
        System.out.println("返回通知=====>"+new Date());
    }
    //异常通知
    public void throwMethod(){
        System.out.println("异常通知=====>"+new Date());
    }
    //后置通知
    public void afterMethod(){
        System.out.println("后置通知=====>"+new Date());
    }

    //环绕通知
    public Object arroundMethod(ProceedingJoinPoint pjp){
        Object obj = null;
        try {
            //环绕通知---前置通知
            System.out.println("环绕通知---前置通知");
            Object[] objs = pjp.getArgs();
            obj = pjp.proceed(objs);
            //环绕通知---返回通知
            System.out.println("环绕通知---返回通知");
        } catch (Throwable throwable) {
            //环绕通知---异常通知
            System.out.println("环绕通知---异常通知");
            throwable.printStackTrace();
        } finally {
            //环绕通知---后置通知
            System.out.println("环绕通知---后置通知");
        }
        return obj;
    }
}

3.配置XML:

XML 复制代码
    <!--开启aop配置-->
    <aop:config>
        <!--切面-->
        <aop:aspect id="mian" ref="loggerUtil">
            <!--切点-->            
            <aop:pointcut id="dian" expression="execution(* *...*.*(..))"/>
            <!--通知-->
            <aop:before method="beforeMethod" pointcut-ref="dian"></aop:before>
            <aop:after-returning method="afterRrturnMethod" pointcut-ref="dian"></aop:after-returning>
            <aop:after-throwing method="throwMethod" pointcut-ref="dian"></aop:after-throwing>
            <aop:after method="afterMethod" pointcut-ref="dian"></aop:after>
            <aop:around method="arroundMethod" pointcut-ref="dian"></aop:around>
        </aop:aspect>
    </aop:config>

2⃣️注解

1.添加依赖:

java 复制代码
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.28</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>

2.创建切面类:

java 复制代码
@Component
@Aspect//切面
//@EnableAspectJAutoProxy 
public class LoggerUtil {
    //切点
    @Pointcut(value="execution(* com.apesource.service.*.*(..))")
    public void dian(){}
    
    //前置通知
//    @Before("dian()")
    public void beforeMethod(){
        System.out.println("前置通知=====>"+new Date());
    }
    //返回通知
//    @AfterReturning("dian()")
    public void afterRrturnMethod(){
        System.out.println("返回通知=====>"+new Date());
    }
    //异常通知
//    @AfterThrowing("dian()")
    public void throwMethod(){
        System.out.println("异常通知=====>"+new Date());
    }
    //后置通知
//    @After("dian()")
    public void afterMethod(){
        System.out.println("后置通知=====>"+new Date());
    }

    //环绕通知
    @Around("dian()")
    public Object arroundMethod(ProceedingJoinPoint point){
        Object returnObj = null;//执行切点方法
        try {
            System.out.println("环绕通知====>前置通知");
            //切点
            Object[] obj = point.getArgs();//切点方法的参数
            returnObj = point.proceed(obj);
            System.out.println("环绕通知====>返回通知");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕通知====>异常通知");
        } finally {
            System.out.println("环绕通知====>后置通知");
        }
        return returnObj;//切点方法的返回值
    }
}

3.配置XML:(也大可不配直接注解)

XML 复制代码
  <!--aop的自动代理 @EnableAspectJAutoProxy可以替换标签-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
相关推荐
用户2986985301416 分钟前
.NET 文档自动化:Spire.Doc 设置奇偶页页眉/页脚的最佳实践
后端·c#·.net
码路飞1 小时前
GPT-5.3 Instant 终于学会好好说话了,顺手对比了下同天发布的 Gemini 3.1 Flash-Lite
java·javascript
序安InToo1 小时前
第6课|注释与代码风格
后端·操作系统·嵌入式
xyy1231 小时前
C#: Newtonsoft.Json 到 System.Text.Json 迁移避坑指南
后端
洋洋技术笔记1 小时前
Spring Boot Web MVC配置详解
spring boot·后端
JxWang051 小时前
VS Code 配置 Markdown 环境
后端
navms1 小时前
搞懂线程池,先把 Worker 机制啃明白
后端
JxWang051 小时前
离线数仓的优化及重构
后端
Nyarlathotep01131 小时前
gin01:初探gin的启动
后端·go
JxWang051 小时前
安卓手机配置通用多屏协同及自动化脚本
后端