学习笔记——Spring中的AOP(AspectJ);Spring中AOP概述;Spring中AOP相关术语;AspectJ中切入点表达式;AspectJ中JoinPoint对象;AspectJ中通知

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

    2023-01-18

    一、Spring中的AOP

    1、AspectJ

    (1)简介

    Java社区里最完整最流行的AOP框架

    在Spring2.0以上版本中,可以使用AspectJ注解或基于XML配置的AOP

    (2)使用AspectJ步骤

    ①在spring核心包的基础上添加支持jar包

    <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.3.10</version>
    </dependency>

    ②创建spring的配置文件,配置自动扫描的包和AspectJ注解支持

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <!--    开启组件扫描-->
        <context:component-scan base-package="com.hh"></context:component-scan>
    <!--    开启AspectJ注解支持-->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>

    ③创建一个类作为切面,在类的上面添加注解

    @Component:将当前类标识为一个组件

    @Aspect:将当前类标识为切面类(非核心业务提取类)

    @Component
    @Aspect
    public class MyLogging {
    
        /**
         * 方法之前
         */
        public static void beforeMethod(String methodName,Object[] arg){
            System.out.println("==>Calc中"+methodName+"方法(),参数:"+ Arrays.toString(arg));
        }
        /**
         * 方法之后
         */
        public static void afterMethod(String methodName,Object rs){
            System.out.println("==>Calc中"+methodName+"方法(),结果:"+rs);
        }
    }

    ④将日志类中的方法添加“通知注解”

    @Before

    ⑤测试

    二、Spring中AOP概述

    1、AOP:Aspect-Oriented Programming,面向切面编程(面向对象的一种补充)

    优势:解决了代码分散与代码混乱的问题

    2、OOP:Object-Oriented Programming,面向对象编程

    三、Spring中AOP相关术语

    1、横切关注点

    非核心业务代码

    2、切面(Aspect)

    将横切关注点提取到类中,这个类称之为切面类

    3、通知(Advice)

    将横切关注点提取到类之后,横切关注点更名为通知

    4、目标(Target)

    目标对象,指的是需要被代理的对象(实现类CalcImpl)

    5、代理(Proxy)

    代理对象可以理解为中介

    6、连接点(Joinpoint)

    通知方法需要指定通知位置,这个位置称之为连接点(通知之前)

    7、切入点(pointcut)

    通知方法需要指定通知位置,这个位置称之为切入点(通知之后)

    四、AspectJ中切入点表达式

    1、语法:@Before(value="execution(权限修饰符 返回值类型 包名.类名.方法名(参数类型))")

    2、通配符

    (1)【*】

    *:可以代表任意权限修饰符&返回值类型

    *:可以代表任意包名、任意类名、任意方法名

    (2)【..】

    ..  代表任意参数类型及参数个数

    3、重用切入点表达式

    (1)使用@PointCut注解,提取可重用的切入点表达式

     //重用切入点表达式
        @Pointcut("execution(* com.hh.aop.CalcImpl.*(..))")
        public void myPointCut(){}

    (2)使用方法名()引入切入点表达式

    @Before(value = "myPointCut()")
    @After("myPointCut()")

    五、AspectJ中JoinPoint对象

    1、JoinPoint:切入点对象

    2、作用:

    (1)获取方法名称

    String methodName = joinPoint.getSignature().getName();

    注:joinPoint.getSignature()  表示方法签名(方法签名=方法名+参数列表)

    (2)获取参数

    Object[] args = joinPoint.getArgs();

    六、AspectJ中通知

    1、前置通知

    (1)语法:@Before

    (2)执行时机:指定方法之前执行

    指定方法:即切入点表达式设置位置

    注:如果目标方法中有异常,会执行

    (3)示例代码

    @Before(value = "myPointCut()")
        public void beforeMethod(JoinPoint joinPoint){
            //获取方法名称
            String methodName = joinPoint.getSignature().getName();
            //获取参数
            Object[] args = joinPoint.getArgs();
            System.out.println("【前置通知】==>Calc中"+methodName+"方法(),参数:"+ Arrays.toString(args));
        }

     

    2、后置通知

    (1)语法:@After

    (2)执行时机:指定方法所有通知执行之后执行

    注:如果目标方法中有异常,会执行

    (3)示例代码

     @After("myPointCut()")
        public void afterMethod(JoinPoint joinPoint){
            //获取方法名称
            String methodName = joinPoint.getSignature().getName();
            //获取参数
            Object[] args = joinPoint.getArgs();
            System.out.println("【后置通知】==>Calc中"+methodName+"方法(),之后执行:"+ Arrays.toString(args));
        }

     

    3、返回通知

    (1)语法:@AfterReturnning

    (2)执行时机:指定方法返回结果时执行

    注:@AfterReturnning中returning属性中的的属性名与入参中参数名一致;

    如果目标方法中有异常,不执行

    (3)示例代码

    @AfterReturning(value = "myPointCut()",returning = "rs")
        public void afterReturnning(JoinPoint joinPoint,Object rs){
            //获取方法名称
            String methodName = joinPoint.getSignature().getName();
            //获取参数
            Object[] args = joinPoint.getArgs();
            System.out.println("【返回通知】==>Calc中"+methodName+"方法(),返回结果执行!结果:"+ rs);
        }

    4、异常通知

    (1)语法:@AfterThrowing

    (2)执行时机::指定方法出现异常时执行

    注:@AfterThrowing中throwing属性中的的属性名与入参中参数名一致;

    如果目标方法中有异常,执行

    (3)示例代码

    @AfterThrowing(value = "myPointCut()",throwing = "ex")
        public void afterThrowing(JoinPoint joinPoint,Exception ex){
            //获取方法名称
            String methodName = joinPoint.getSignature().getName();
            //获取参数
            Object[] args = joinPoint.getArgs();
            System.out.println("【异常通知】==>Calc中"+methodName+"方法(),出现异常时执行!异常:"+ ex);
        }

    说明:

    ①有异常:前置通知—>异常通知—>后置通知

    ②无异常:前置通知—>返回通知—>后置通知

    5、环绕通知(前四个通知整合)

    (1)语法:@Around

    (2)作用:整合前四个通知

    (3)注意:参数中必须使用ProceedingJoinPoint

    (4)示例代码

     @Around(value = "myPointCut()")
        public Object aroundMethod(ProceedingJoinPoint pjp){
    
            //获取方法名称
            String methodName = pjp.getSignature().getName();
            //获取参数
            Object[] args = pjp.getArgs();
            //定义返回值
            Object rs = null;
            try {
                //前置通知 )
                System.out.println("【前置通知】==>Calc中"+methodName+"方法(),参数:"+ Arrays.toString(args));
                //触发目标对象的目标方法(加减乘除)
                rs = pjp.proceed();
                //返回通知(有异常不执行
                System.out.println("【返回通知】==>Calc中"+methodName+"方法(),返回结果执行!结果:"+ rs);
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                //异常通知
                System.out.println("【异常通知】==>Calc中"+methodName+"方法(),出现异常时执行!异常:"+ throwable);
            }finally {
                //后置通知(有异常执行)
                System.out.println("【后置通知】==>Calc中"+methodName+"方法(),之后执行:"+ Arrays.toString(args));
            }
            return rs;
        }

     

  • 阿里云国际版折扣https://www.yundadi.com

  • 阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
    标签: Spring