Spring boot aop集成(面向切面的编程)

Spring boot面向切面的编程

官方文档

https://docs.spring.io/spring-boot/reference/features/aop.html#page-title

aop默认的配置

aop默认的代理方式CGLib

复制代码
spring.aop.proxy-target-class=true

启用JDK代理修改配置

To use JDK proxies instead, set configprop:spring.aop.proxy-target-class to false.

复制代码
spring.aop.proxy-target-class=false

关于aop的开启配置

If AspectJ is on the classpath, Spring Boot's auto-configuration will automatically enable AspectJ auto proxy such that @EnableAspectJAutoProxy is not required.

只要引入aspectjweaver就默认开启aop

项目准备

springboot

  • spring boot 3.3.3

  • Jdk17

添加依赖

复制代码
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.22</version>
</dependency>

添加依赖后自动启用AspectJ

更多官方文档:https://docs.spring.io/spring-framework/reference/core/aop/ataspectj.html

编写配置类

复制代码
package com.demo.springbootaop.aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Aspect
@Order(1)
@Component
public class MyAspect {
    //切入点
    @Pointcut("execution(* com.demo.springbootaop.controller.*.*(..))")
    public void dsPointCut() {

    }
 		/**
     * 通知类型
     * Around 环绕通知
     * Before 前置通知
     * AfterReturning 后置通知
     * AfterThrowing 异常通知
     * After 最终通知
     * 
     */
    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知开始。。。。 ");
        Object proceed = point.proceed();
        System.out.println("环绕通知结束。。。。 ");
        return proceed;

    }
}

当有两个切面在同一个配置类里面时执行顺序

复制代码
package com.demo.springbootaop.aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Aspect
@Order(1)
@Component
public class MyAspect {
    //切入点

    /**
     * 如何匹配切入点
     * execution(返回值类型 包名.类名.方法名(参数))
     * 更多匹配类型参考官方文档:<a href="https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html">...</a>
     */
    @Pointcut("execution(* com.demo.springbootaop.controller.*.*(..))")
    public void dsPointCut() {

    }

    /**
     * 根据注解切入
     * "@Annotation(com.demo.springbootaop.annotation.MyAnnotation)"
     */
    @Pointcut("(@within(org.springframework.web.bind.annotation.RestController))")
    public void pcAnnotation() {

    }

    /**
     * 通知类型
     * Around 环绕通知
     * Before 前置通知
     * AfterReturning 后置通知
     * AfterThrowing 异常通知
     * After 最终通知
     *
     */

    @Around("pcAnnotation()")
    public Object aroundRestController(ProceedingJoinPoint point) throws Throwable {
        System.out.println("RestController环绕通知开始。。。。 ");
        Object proceed = point.proceed();
        System.out.println("RestController环绕通知结束。。。。 ");
        return proceed;

    }
    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知开始。。。。 ");
        Object proceed = point.proceed();
        System.out.println("环绕通知结束。。。。 ");
        return proceed;

    }
}

执行结果

复制代码
环绕通知开始。。。。 
RestController环绕通知开始。。。。 
RestController环绕通知结束。。。。 
环绕通知结束。。。。 

暂时不确定一个配置类里面多个切入点执行顺序是如何设定的

多个配置类

复制代码
package com.demo.springbootaop.aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Aspect
@Order(2)
@Component
public class MyAspect {
    /**
     * 如何匹配切入点
     * execution(返回值类型 包名.类名.方法名(参数))
     * 更多匹配类型参考官方文档:<a href="https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html">...</a>
     */
    @Pointcut("execution(* com.demo.springbootaop.controller.*.*(..))")
    public void dsPointCut() {

    }
    /**
     * 通知类型
     * Around 环绕通知
     * Before 前置通知
     * AfterReturning 后置通知
     * AfterThrowing 异常通知
     * After 最终通知
     *
     */


    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        System.out.println("环绕通知开始。。。。 ");
        Object proceed = point.proceed();
        System.out.println("环绕通知结束。。。。 ");
        return proceed;
    }

}

package com.demo.springbootaop.aop;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;


@Aspect
@Order(1)
@Component
public class MyAspect1 {
    //切入点
    /**
     * 根据注解切入
     * "@Annotation(com.demo.springbootaop.annotation.MyAnnotation)"
     */
    @Pointcut("(@within(org.springframework.web.bind.annotation.RestController))")
    public void pcAnnotation() {

    }
    /**
     * 如何匹配切入点
     * execution(返回值类型 包名.类名.方法名(参数))
     * 更多匹配类型参考官方文档:<a href="https://docs.spring.io/spring-framework/reference/core/aop/ataspectj/pointcuts.html">...</a>
     */




    /**
     * 通知类型
     * Around 环绕通知
     * Before 前置通知
     * AfterReturning 后置通知
     * AfterThrowing 异常通知
     * After 最终通知
     *
     */


    @Around("pcAnnotation()")
    public Object aroundRestController(ProceedingJoinPoint point) throws Throwable {
        System.out.println("RestController环绕通知开始。。。。 ");
        Object proceed = point.proceed();
        System.out.println("RestController环绕通知结束。。。。 ");
        return proceed;

    }
}

执行结果

复制代码
RestController环绕通知开始。。。。 
环绕通知开始。。。。 
环绕通知结束。。。。 
RestController环绕通知结束。。。。

结论:

复制代码
@Order(1)

值越小优先级越高

注意:环绕通知 先执行的后结束,后执行的先结束

相关推荐
@yanyu66610 分钟前
idea中配置tomcat
java·mysql·tomcat
2501_9167665412 分钟前
【项目部署】JavaWeb、MavenJavaWeb项目部署至 Tomcat 的实现方式
java·tomcat
RoboWizard23 分钟前
扩容刚需 金士顿新款Canvas Plus存储卡
java·spring·缓存·电脑·金士顿
lang2015092839 分钟前
Spring Boot 入门:5分钟搭建Hello World
java·spring boot·后端
失散131 小时前
分布式专题——47 ElasticSearch搜索相关性详解
java·分布式·elasticsearch·架构
serve the people1 小时前
LangChain 表达式语言核心组合:Prompt + LLM + OutputParser
java·langchain·prompt
想ai抽1 小时前
深入starrocks-多列联合统计一致性探查与策略(YY一下)
java·数据库·数据仓库
武子康1 小时前
Java-152 深入浅出 MongoDB 索引详解 从 MongoDB B-树 到 MySQL B+树 索引机制、数据结构与应用场景的全面对比分析
java·开发语言·数据库·sql·mongodb·性能优化·nosql
杰克尼1 小时前
JavaWeb_p165部门管理
java·开发语言·前端