一、AOP 的相关概念
1.1 AOP 概述:
1.1.1 什么是 AOP:
AOP全称是 Aspect Oriented Programming 即:面向切面编程。 简单的说它就是把我们程序重复的代码抽取出来,在需要执行的时候,使用动态代理的技术,在不修改源码的基础上,对我们的已有方法进行增强。
1.1.2 AOP 的作用及优势:
作用: 在程序运行期间,不修改源码对已有方法进行增强。
优势:
减少重复代码
提高开发效率
维护方便
1.1.3 AOP 的实现方式:使用动态代理技术
1.2 AOP 的具体应用:
1.2.1 开发中出现的问题:
当我们控制数据库进行增删改查操作时,我们使用 connection 对象的 setAutoCommit(true) 此方式控制事务,如果我们每次都执行一条 sql 语句,没有问题,但是如果业务方法一次要执行多条 sql 语句,这种方式就无法实现功能了。
当我们执行多条sql语句时,如果执行的过程中有异常,由于我们每次执行持久层方法都是独立事务,导致无法实现事务控制(不符合事务的一致性)
解决办法: 让业务层来控制事务的提交和回滚
1.2.2 业务层来控制事务的提交和回滚出现的新问题:
通过对业务层改造,已经可以实现事务控制了,但是由于我们添加了事务控制, 导致业务层方法变得臃肿了,里面充斥着很多重复代码。并且业务层方法和事务控制方法耦合了。
如果此时提交,回滚,释放资源中任何一个方法名变更,都需要修改业务层的代码,非常的不方便。
解决方案:使用动态代理
1.2.3 动态代理回顾
1.2.3.1 动态代理的特点:字节码随用随创建,随用随加载。
1.2.3.2 动态代理常用的两种方式:
基于接口的动态代理:
提供者:JDK 官方的 Proxy 类。
要求:被代理类最少实现一个接口。
基于子类的动态代理:
提供者:第三方的 CGLib,如果报 asmxxxx 异常,需要导入 asm.jar。
要求:被代理类不能用 final 修饰的类(最终类)。
1.2.3.3 使用基于接口的动态代理:
1.2.4 使用动态代理解决事务问题:
总结:当我们使用动态代理之后,业务层用于控制事务的重复代码就都可以删掉了。
二、Spring 中的 AOP
2.1 Spring 中 AOP 的细节
2.1.1 说明:我们学习spring的 aop,就是通过配置的方式,实现上一章节的功能。
2.1.2 AOP 相关术语:
Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在 spring 中,这些点指的是方法,因为 spring 只支持方法类型的连接点。
Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义
Advice(通知/增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知。 通知的类型:前置通知,后置通知,异常通知,最终通知,环绕通知。 Introduction(引介): 引介是一种特殊的通知在不修改类代码的前提下, Introduction 可以在运行期为类动态地添加一些方法或 Field。
Target(目标对象): 代理的目标对象。
Weaving(织入): 是指把增强应用到目标对象来创建新的代理对象的过程。 spring 采用动态代理织入,而 AspectJ 采用编译期织入和类装载期织入。
Proxy(代理): 一个类被 AOP 织入增强后,就产生一个结果代理类。 Aspect(切面): 是切入点和通知(引介)的结合。
2.2 基于 XML 的 AOP 配置:
2.2.1 环境搭建:
2.2.1.1 第一步:准备必要的代码: 此处包含了实体类,业务层和持久层代码。
2.2.1.2 第二步:拷贝必备的 jar 包到工程的 lib 目录
2.2.1.3 第三步:创建 spring 的配置文件并导入约束
2.2.1.4 第四步:配置 spring 的 ioc
2.2.1.5 第五步:抽取公共代码制作成通知
2.2.2 配置步骤
2.2.2.1 第一步:把通知类用 bean 标签配置起来
2.2.2.2 第二步:使用 aop:config 声明 aop 配置
aop:config
作用:用于声明开始 aop 的配置
<配置代码>
2.2.2.3 第三步&#xff1a;使用 aop:aspect 配置切面
2.2.2.4 第四步&#xff1a;使用 aop:pointcut 配置切入点表达式
2.2.2.5 第五步&#xff1a;使用 aop:xxx 配置对应的通知类型
aop:before
作用&#xff1a; 用于配置前置通知。指定增强的方法在切入点方法之前执行
属性&#xff1a;
method:用于指定通知类中的增强方法名称
ponitcut-ref&#xff1a;用于指定切入点的表达式的引用
poinitcut&#xff1a;用于指定切入点表达式
执行时间点&#xff1a;
切入点方法执行之前执行
aop:after-returning
作用&#xff1a; 用于配置后置通知
属性&#xff1a;
method&#xff1a;指定通知中方法的名称。
pointct&#xff1a;定义切入点表达式
pointcut-ref&#xff1a;指定切入点表达式的引用
执行时间点&#xff1a;
切入点方法正常执行之后。它和异常通知只能有一个执行
aop:after-throwing
作用&#xff1a; 用于配置异常通知
属性&#xff1a;
method&#xff1a;指定通知中方法的名称。
pointct&#xff1a;定义切入点表达式
pointcut-ref&#xff1a;指定切入点表达式的引用
执行时间点&#xff1a;
切入点方法执行产生异常后执行。它和后置通知只能执行一个
aop:after
作用&#xff1a; 用于配置最终通知
属性&#xff1a;
method&#xff1a;指定通知中方法的名称。
pointct&#xff1a;定义切入点表达式
pointcut-ref&#xff1a;指定切入点表达式的引用
执行时间点&#xff1a;
无论切入点方法执行时是否有异常&#xff0c;它都会在其后面执行。
2.2.3 切入点表达式说明&#xff1a;
execution:匹配方法的执行(常用)
execution(表达式)
表达式语法&#xff1a;execution([修饰符] 返回值类型 包名.类名.方法名(参数))
通常情况下&#xff0c;我们都是对业务层的方法进行增强&#xff0c;所以切入点表达式都是切到业务层实现类&#xff1a;
execution(* com.itheima.service.impl.*.*(..))
2.2.4 环绕通知
2.3基于注解的 AOP 配置
2.3.1 环境搭建
2.3.1.1 第一步&#xff1a;准备必要的代码和 jar 包
2.3.1.2 第二步&#xff1a;在配置文件中导入 context 的名称空间
2.3.1.3 第三步&#xff1a;把资源使用注解配置
2.3.1.4 第四步&#xff1a;在配置文件中指定 spring 要扫描的包
2.3.2 配置步骤
2.3.2.1 第一步&#xff1a;把通知类也使用注解配置
2.3.2.2 第二步&#xff1a;在通知类上使用&#64;Aspect 注解声明为切面
2.3.2.3 第三步&#xff1a;在增强的方法上使用注解配置通知
2.3.2.4 第四步&#xff1a;在 spring 配置文件中开启 spring 对注解 AOP 的支持