一文带你了解sprinboot AOP和简单使用

发布于:2023-10-25 ⋅ 阅读:(229) ⋅ 点赞:(0)

前言

这是我在这个网站整理的笔记,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱

什么是AOP?

AOP(面向切面编程)是一种编程范式,它允许我们在程序运行时通过将横切关注点(如日志记录、事务管理等)从核心业务逻辑中分离出来,以提高代码的可重用性和可维护性。

Spring Boot AOP的优势

Spring Boot提供了强大的AOP支持,使得我们可以更轻松地实现横切关注点的功能。以下是Spring Boot AOP的一些优势:

  1. 模块化开发:AOP让我们能够将横切关注点与核心业务逻辑分离,从而使代码更易于理解和维护。
  2. 代码重用:通过将通用的横切关注点封装成切面,我们可以在多个模块或项目中重复使用,避免重复编写相同的代码。
  3. 运行时动态代理:Spring Boot AOP使用动态代理技术,在程序运行时动态地将切面织入到目标对象中,而无需修改目标对象的源代码。

Spring Boot AOP的使用步骤

以下是使用Spring Boot AOP的一般步骤:

  1. 定义切面类:创建一个切面类,该类包含了我们想要在目标方法执行前、执行后或出现异常时执行的逻辑。
  2. 定义切点:定义一个切点,它表示我们希望在哪些方法上应用切面逻辑。
  3. 配置AOP:在配置类中配置AOP,指定要扫描的包和切面类。
  4. 测试:编写测试代码,验证AOP是否按预期工作。

AOP相关名词解释

在理解Spring Boot AOP的过程中,以下是一些常见的名词和概念:

  1. 切面(Aspect):切面是横切关注点的具体实现。它包含了在目标方法执行前、执行后或出现异常时要执行的逻辑。切面可以被应用于一个或多个切点。
  2. 切点(Pointcut):切点是在应用程序中选择连接点的表达式。连接点是在应用程序中可以插入切面的特定位置,如方法执行前、执行后或出现异常时等。切点使用表达式语言来定义要拦截的方法。
  3. 连接点(Join Point):连接点是在应用程序执行期间可以插入切面的特定位置。它可以是方法调用、方法执行、异常抛出等。
  4. 通知(Advice):通知是切面在连接点上执行的具体操作。Spring提供了以下几种通知类型:前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。
  5. 织入(Weaving):织入是将切面应用到目标对象中的过程。Spring AOP使用动态代理或字节码增强来实现织入。
  6. 目标对象(Target Object):目标对象是应用程序中被代理的对象,它包含了核心业务逻辑。
  7. 代理(Proxy):代理是一个包装了目标对象的对象,它拦截对目标对象的方法调用,并在必要时调用切面逻辑。

以上是一些常见的AOP相关名词,理解这些名词将有助于更好地理解和应用Spring Boot AOP。

springboot实现AOP

在Spring Boot中,可以使用@Aspect注解实现AOP(面向切面编程)。以下是几种常见的方式:

  1. 测试条件

    在service层定义一个HelloWord对象:

    @Service
    public class HelloWord {
        public String helloWord() {
            return "你好";
        }
    }
    

    编写测试类

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = ChenApplication.class)
    public class TestMethod {
    
        @Autowired
        private HelloWord helloWords;
    
        @Test
        public void helloTest() {
    
            System.out.println(helloWords.helloWord());
        }
    }
    
    
  2. 基于方法:使用@Before@After@AfterReturning@AfterThrowing@Around等注解来定义通知(Advice)方法,这些方法将在目标方法执行前、执行后、返回结果后或抛出异常时执行。

    例如:

    @Aspect
    @Component
    public class BeforeAspect {
        @Before("execution(* com.chen.service.HelloWord.*(..))")
        public void beforeAdvice(JoinPoint joinPoint) {
            // 在目标方法执行前执行的逻辑
            System.out.println("执行方法前的操作");
        }
    }
    

    image-20231020171127002

  3. 基于注解:使用@Pointcut和自定义注解来定义切点(Pointcut),并通过@Around注解的通知方法来拦截带有特定注解的方法。

    例如:

    定义注解

    @Target({ ElementType.PARAMETER, ElementType.METHOD })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Hello {
    
        public String name() default "";
    }
    

    定义AOP

    @Aspect
    @Component
    public class AroundHello {
    
    
    //    定义切点: 基于注解
        @Pointcut("@annotation(com.chen.common.config.aspectj.annotation.Hello)")
        public void aroundHello() {}
    
    //    环绕通知
        @Around("aroundHello()")
        public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
            // 在目标方法执行前执行的逻辑
            System.out.println("执行前");
            // 在目标方法返回结果后执行的逻辑
            Object result = proceedingJoinPoint.proceed();
            Hello annotationHello = getAnnotationHello(proceedingJoinPoint);
            if (annotationHello != null) {
                System.out.println("执行后" + annotationHello.name() + "," + result);
            }
            return result;
    
        }
    
        /**
         * 是否存在注解,如果存在就获取
         */
        private Hello getAnnotationHello(JoinPoint joinPoint) throws Exception {
            Signature signature = joinPoint.getSignature();
            MethodSignature methodSignature = (MethodSignature)signature;
            Method method = methodSignature.getMethod();
    
            if (method != null) {
                return method.getAnnotation(Hello.class);
            }
            return null;
        }
    }
    

    测试结果

    image-20231020180258284

  4. 基于类或接口:使用@Pointcut注解和类或接口的匹配表达式来定义切点,然后通过其他通知注解来定义通知方法。

    例如:

    @Service
    public class HelloWord {
        public String helloWord() {
            System.out.println("你好呀");
            return "你好";
        }
    }
    
    @Aspect
    @Component
    public class AfterAspect {
        @Pointcut("within(com.chen.service.*)")
        public void serviceMethods() {}
    
        @After("serviceMethods()")
        public void afterAdvice(JoinPoint joinPoint) {
            // 在目标类中的方法执行后执行的逻辑
            System.out.println("方法执行后");
        }
    }
    
    

这些是一些常见的使用@Aspect注解实现AOP的方式。通过定义切点和通知方法,可以在适当的时机拦截和处理目标方法的调用。具体选择哪种方式取决于你的需求和场景。

测试结果

image-20231023113601976

作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。


网站公告

今日签到

点亮在社区的每一天
去签到