Spring学习 | AOP
admin
2024-03-27 11:15:33
0次

文章目录

  • 一、简介
  • 二、AOP操作
    • 2.1 操作术语
    • 2.2 操作实现
      • 2.2.1 实现原理
      • 2.2.2 具体实现


学习视频🎥:https://www.bilibili.com/video/BV1Vf4y127N5

一、简介

💬概述:Aspect Oriented Programming 面向切面(方面)编程,意思是不通过修改源代码的方式,在主干功能上添加新的功能

🔑作用与目的:利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率

🔑AOP底层原理:AOP底层通过动态代理实现,根据有无接口将动态代理分为两种——JDK和CGLIB

❓ 动态代理:代理模式的实现方式之一,即在在内存中形成代理类

  1. JDK动态代理:需要增强的是接口中的方法,则要创建对应接口的实现类代理对象,通过实现类代理对象增强方法功能,可以通过Proxy 类来实现
  2. CGLIB动态代理:需要增强的是普通类(POJO)的方法,则要创建对应类的子类代理对象,通过子类代理对象增强方法的功能

二、AOP操作

2.1 操作术语

  • 连接点(Joinpoint):可以被增强的方法
  • 切入点(Pointcut):实际被增强的方法
  • 通知、增强(Advice):实现增强功能的逻辑部分(增强代码),有5种通知类型
    ① 前置通知:在被增强的方法前执行
    ② 后置通知(返回通知):在被增强的方法后(方法返回值之后)执行,如果方法出现异常可能不会执行
    ③ 环绕通知:在被增强的方法前后都执行
    ④ 异常通知:被增强的方法出现异常时执行
    ⑤ 最终通知:在被增强的方法后执行,类似于finally语句,即不管被增强的方法是否出现异常都会执行
  • 切面:表示一个动作——将通知应用到切入点上(实现增强功能)

2.2 操作实现

2.2.1 实现原理

🔑基于AspectJ:Spring AOP一般都是基于AspectJ 实现的

💡 AspectJ 不是Spring的组成部分,实际上是对AOP编程思想的一个实践,

🔑切入点表达式:在进行AOP的配置时,需要使用切入点表达(作为属性值)

🔑作用:指定和标识出需要增强的类和方法

🔑语法格式:execution([权限修饰符] [返回类型] [被增强的类的全类名].[被增强的方法名](参数列表));

  • 权限修饰符一般用 *代替,表示全部权限修饰符都符合
  • 返回类型可以省略
  • 参数列表用..代替

🔑案例(用*表示所有)

  • 标识出具体的被增强类和被增强方法:execution(* com.Key.dao.UserDao.add(..));
  • 标识出具体的被增强类,类中所有方法都被增强:execution(* com.Key.dao.UserDao.*(..));
  • 只标识出具体的包,包中所有类和类中所有方法都被增强:execution(* com.Key.dao.*.*(..));

🔑导入相关jar包:spring-aspects-…jar、com.springsource.net.sf.cglib-…jar、com.springsource.org.aopalliance-…jar、com.springsource.org.aspectj.weaver-…jar

2.2.2 具体实现

🔑注解方式实现(重点)

① 创建需要被增强的类和方法

② 创建增强类,在类中创建多个方法,通过在方法上添加注解,使每个方法对应不同的通知类型(5种)

💡 以上每个注解中都有一个属性value,属性值就是切入点表达式,通过切入点表达式精确找到被增强类和方法

  • @Before:对应前置通知

    // 前置通知
    @Before(value = "execution(* com.Key.bean.User.add(..))")
    public void before() {System.out.printf("增强方法——前置通知");
    }
    
  • @AfterReturning:对应后置通知(返回通知)

    // 后置通知
    @AfterReturning(value = "execution(* com.Key.bean.User.add(..))")
    public void afterReturning() {System.out.printf("增强方法——后置通知");
    }
    
  • @Around:对应环绕通知

    💡 环绕通知在被增强方法前后都执行,则需要添加一个形参ProceedingJoinPoint proceedingJoinPoint,然后调用该形参的方法——proceed()执行被增强的方法

    // 环绕通知
    @Around(value = "execution(* com.Key.bean.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.printf("方法前执行");// 执行被增强的方法proceedingJoinPoint.proceed();System.out.printf("方法后执行");
    }
    
  • @AfterThrowing:对应异常通知

    // 异常通知
    @AfterThrowing(value = "execution(* com.Key.bean.User.add(..))")
    public void afterThrowing() {System.out.printf("增强方法——异常通知");
    }
    
  • @After:对应最终通知

    // 最终通知
    @After(value = "execution(* com.Key.bean.User.add(..))")
    public void after() {System.out.printf("增强方法——最终通知");
    }
    

③ 实现通知(增强)的配置

  • 在spring 配置文件中开启组件扫描(使用注解的必须操作)

    
    
  • 使用注解创建出被增强类对象以及增强类对象:在对应类上添加@Component注解即可

    // 创建被增强类对象
    @Component(value = "user")
    public class User {// 被增强方法public void add() {System.out.println("被增强方法...");}
    }/*+----------------------------------------------------+*/// 创建增强类对象
    @Component(value = "userProxy")
    public class UserProxy {// 增强方法(前置通知)@Before(value = "execution(* com.Key.bean.User.add(..))")public void before() {System.out.printf("增强方法——前置通知");}
    }
    
  • 使用注解创建代理对象:在增强类上添加@Aspect注解

    // 创建增强类对象并创建出对应的代理对象
    @Component(value = "userProxy")
    @Aspect
    public class UserProxy {// 增强方法(前置通知)@Before(value = "execution(* com.Key.bean.User.add(..))")public void before() {System.out.printf("增强方法——前置通知");}
    }
    
  • 开启代理对象

    1️⃣. xml 文件配置:先开启aop 名称空间,再使用标签

    
    

    2️⃣. 使用注解(完全注解开发):创建配置类,在配置类上添加@EnableAspectJAutoProxy,注解中添加proxyTargetClass属性,属性值置为true(默认是false)

    @Configuration
    @ComponentScan(basePackage = {"com.Key"})
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    public class SpringConfig {// code...
    }
    

④ 抽取公共切入点

  • 使用:在增强类中创建一个方法pointCut(),方法上添加@Pointcut注解,注解中添加value属性(可省略),属性值就是抽取出来的公共切入点表达式,将含有公共切入点表达式的增强方法上的表达式都改成pointCut()即可

    // 抽取公共切入点
    @Pointcut(value = "execution(* com.Key.bean.User.add(..))")
    public void pointCut() {// code...
    }@After(value = "pointCut()")
    public void after() {// code...
    }
    
  • 作用:减少冗余的表达式,而且修改表达式时只需要修改一处即可

⑤ 设置增强类优先级:当有多个增强类对同一个类及其方法进行增强时,需要对每个增强类设置优先级。在每个增强类上添加@Order注解,注解中添加一个整数值,该数值越小优先级越高

// 设置优先级为1的增强类
@Component("uP")
@Aspect
@Order(1)
public class UserProxy {@Beforepublic void before() {System.out.println("增强方法");}
}

🔑xml 文件配置(了解即可)

① 创建被增强类和增强类,以及各自的方法

② 在spring 配置文件中创建被增强类对象和增强类对象




③ 在spring 配置文件中配置切入点:需要先引入aop 名称空间




相关内容

热门资讯

AI做攻略、“双向奔赴”……国... 本文转自:人民网人民网记者 许维娜今年国庆假期,AI(人工智能)成了不少年轻人的“旅行搭子”。行前做...
合肥的这个“梗”, 翻篇了 社交平台的评论区,曾长期流传一句专属于合肥的黑色幽默。有人问合肥哪里好玩,本地网友半开玩笑地回复:合...
7万+旅游中高层都在的群,今天... 做旅游这行,资源卡位、渠道互通、项目落地——往往就差一个“对的机会”。我们的行业社群已聚集70,00...
一场帐篷音乐节,如何让井研从“... 帐篷音乐节现场封面新闻记者 周洪攀10月的研溪湿地,晚风里裹着柑橘的清甜与民谣的回响。夜幕降临,10...
白鹤翩翩落星愿,上海迪士尼度假... 10月9日,世界候鸟日前夕,上海迪士尼度假区星愿公园的湖风里多了一分白鹤的灵动。三座白鹤雕塑正式揭幕...
成都锦江边赏初秋枫叶飘飘 目前,成都锦江边国华街枫叶树红了。近年来,国华街附近的几条街都栽种了红枫树,是城区较集中看枫叶的点位...
GBTA:商务旅行正在复苏,但... 亚太正在成为全球商务旅行增长的重要引擎。在经历疫情后的快速反弹之后,全球商务旅行正在进入一个新的增长...
从景区焕新到节赛引流 邹城双节... 齐鲁网·闪电新闻10月9日讯 中秋、国庆“双节”假期,邹城市文化和旅游局提前谋划、周密部署,立足自身...
江山如此多娇 且看石楼今朝 金秋十月,黄河岸畔秋意盎然,丰收盛会喜迎国庆。本次石楼国庆文旅活动以“江山如此多娇,且看石楼今朝”为...
海南国庆假期接待游客475.4... 2026年国庆假期,海南接待游客475.40万人次,较2025年增长13.1%,较2024年增长15...