AOP:
当我们在service层调用mapper层时,其实不是调用的mapper层接口,因为在接口中无法调用对象,那我们真正调用的是mapper层的实现类,但这个实现类并不是我们写的代码,而是通过代理,实现的
目标对象是拿到mapper层接口里的方法,代理对象是mapper的Impl类,调用者是service层
可以借助实现类代理实现里面的调用
代理模式:
动态代理:jdk动态代理
静态代理
a(调用者)找到b(代理人)进行代理实现c(目标对象)的方法 mybatis动态代理常用jdk动态代理




在目标对象只唱歌的基础上通过代理对象进行增强也就是加入其他业务功能,调用者就是test类

例如:在操作新增数据字典时,我们要记录日志,但是目标就是新增数据字典,记录日志信息不是它的目标,所以这时候日志就是通过代理对象来实现的
也就是与核心业务无关的事情就交给代理对象实现,这就实现了核心功能的增强
在idea的test下建一个proxy代理包进行测试
使用静态代理方法:






回顾之前学习Mybatis时候,映射接口如下:


也就是TargetImpl对象要实现一个或多个接口
我们这里是一个接口

Instance实例对象
JavaAPI源码分析:


测试类






AOP基础:AOP也是spring框架的第二大核心





如果相对目标方法增强,不想修改原来业务的接口,那就使用AOP进行增强,给所有接口记录请求耗时,这属于共有的功能:
1.引入AOP依赖

2.编写AOP程序,针对特定方法(记录请求耗时),进行编程------在common下新建aspect(切面)包
要在类TimeAspect上加:
@Slf4j:日志输出
@Aspect切面注解:代表当前类是切面类
@component将当前类对象TimeAspect交给spring容器管理,不属于controller,service,mapper层,所以加这个注解
@Around环绕通知:在核心方法前执行记录一个时间,也就是核心方法执行前执行一部分代码 ,中间执行核心业务 ,后面记录结束时间也就是核心方法执行后执行一段代码

加上这个execution后会有向外的m箭头,对应可以看到service业务层有切入的箭头






连接点:JoinPoint
连接点指的是可以被AOP控制的方法。
通过joinpoint可以控制方法对核心业务进行调用
重新启动SpringBoot程序,在knife4j中新增图书或者登录等业务,查看耗时
这里以登录为例:



1.记录系统操作日志:每一个接口统一进行处理
2.权限控制:指定用户访问,对接口进行统一的权限校验
3.事务管理






在那些方法上添加共有的逻辑就叫做切面

controller要调用service才能实现核心方法,所以service是目标对象


在service打印输出一下bookservice的字节码对象名称,之前在切面类书写了耗时记录的方法,所以在接口文档中测试更新书籍的方法,最后输出的结果可以看到是CGlib动态代理的


异常和环绕核心方法只能执行一个,有异常会先执行异常通知,没有异常就不会执行异常通知,就会执行环绕通知的核心方法执行后的通知




如果在接口文档中登录密码写错,有异常,就是执行异常通知,核心方法执行后的通知就不会被执行




AfterReturning目标方法执行后通知,有异常不执行
AfterThrowing发生异常后执行

测试登录接口时,如果两个方法都要执行,谁的返回值是object类型谁就优先返回


定义为public可以在其他类中引用这个公共的切点,用包名.pc方法来表示



当有对个切面通知,并且他们作用于同一个方法时,那个通知先执行?
答案:A-->B-->C
A <--B<--C
就是按照一条线执行,环状执行
这里写了一个AAspect切面类,B和C代码一样




核心方法前面执行是按照字母顺序返回,后面是字母顺序靠后的先执行

如果想指定A先执行,可以借助order(3)指定A最后运行













想对哪个方法增强就在那个方法中把自己定义的注解写上去

在接口文档中测试用户名登录,可以查看到切面类打印的信息





fastjson可以将字符串转换成json格式,可以讲令牌信息转换成json格式




在接口文档中测试登录后,运行结果如上图