Spring5 底层原理 jdk 和 cglib 在 Spring 中的统一(黑马)

切点、通知、切面

Spring 中对切点、通知、切面的抽象如下

  • 切点:接口 Pointcut,典型实现 AspectJExpressionPointcut
  • 通知:典型接口为 MethodInterceptor 代表环绕通知
  • 切面:Advisor,包含一个 Advice 通知,PointcutAdvisor 包含一个 Advice 通知和一个 Pointcut
«interface»
Advice
«interface»
MethodInterceptor
«interface»
Advisor
«interface»
PointcutAdvisor
«interface»
Pointcut
AspectJExpressionPointcut

代理相关类图

  • AopProxyFactory 根据 proxyTargetClass 等设置选择 AopProxy 实现
  • AopProxy 通过 getProxy 创建代理对象
  • 图中 Proxy 都实现了 Advised 接口,能够获得关联的切面集合与目标(其实是从 ProxyFactory 取得)
  • 调用代理方法时,会借助 ProxyFactory 将通知统一转为环绕通知:MethodInterceptor
使用
创建
创建
«interface»
Advised
ProxyFactory
proxyTargetClass : boolean
Target
Advisor
«interface»
AopProxyFactory
«interface»
AopProxy
+getProxy() : Object
基于CGLIB的Proxy
ObjenesisCglibAopProxy
advised : ProxyFactory
JdkDynamicAopProxy
advised : ProxyFactory
基于JDK的Proxy

两个切面概念

        aspect =
            通知1(advice) +  切点1(pointcut)
            通知2(advice) +  切点2(pointcut)
            通知3(advice) +  切点3(pointcut)
            ...
        advisor = 更细粒度的切面,包含一个通知和切点
        
        总结:一个aspect 其实底层最终会拆解为advisor,所以笔者认为对advisor的理解会使我们更好理解aspect

一般我们写的代码大概是这样的
在这里插入图片描述

advisor执行流程

准备好切点

切点在spring中用一个叫Pointcut的接口来表示

在这里插入图片描述
查看源码发现由对class进行匹配的与对方法进行匹配的抽象方法,其中也提供了很多的子实现
在这里插入图片描述
比如注解匹配的、AspectJ表达式匹配的,这里我们选后者为例
在这里插入图片描述
看完上面解释之后我们开正式创建切点:

  • 创建切点对象
  • 设置切点表达式
    在这里插入图片描述
    测试类如下:
    在这里插入图片描述

准备好通知

spring中通知也有很多的实现,这里我们说一个基本、也是重要的一个通知,基本其他通知最终都会转换为这个通知来执行,这个通知的名字为MethodInterceptor,这里不要与前面的一个同名接口弄混了,注意为下图这个,spring用的是第三方 接口定义

在这里插入图片描述
这个接口里只有一个抽象方法,所以作为一个函数式接口(抽象方法里就可以写我们想要的增强功能,本质上属于一种环绕通知)
在这里插入图片描述
创建通知:

  • 创建通知实例
  • 增强逻辑、调用目标
    在这里插入图片描述

准备好切面

这个比较简单吗,我们找一个比较简单的实现,这里在构造时传入切点与通知
在这里插入图片描述
在这里插入图片描述

创建代理

我们这里就不用与代理底层打交道了,用一个ProxyFactory来创建,这里ProxyFactory会根据情况选择JDK实现或者cglib的实现

情况分类:

  1. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现
  2. proxyTargetClass = false, 目标没有实现接口, 用 cglib 实现
  3. proxyTargetClass = true, 总是使用 cglib 实现

创建代理流程:

  • 设置目标
  • 加入切面(可选加入一个或多个)
  • 创建代理对戏(调用ProxyFactory的getProxy方法可实现创建,这里我们转换一下类型,因为我们要调用测试类接口的方法)

在这里插入图片描述
调用一下方法测试一下:
在这里插入图片描述

预期foo方法增强,bar方法不增强,结果如下(第一个是我为了看代理是由什么实现的用的cglib增强):
在这里插入图片描述

情况分类(代理选择情况分类):

  1. proxyTargetClass = false, 目标实现了接口, 用 jdk 实现
  2. proxyTargetClass = false, 目标没有实现接口, 用 cglib 实现
  3. proxyTargetClass = true, 总是使用 cglib 实现

没有设置这个的话默认为目标没有实现任何接口(即使实现了也会装作看不见)
在这里插入图片描述
设置之后就会判断是否实现接口,之后就会按照上面情况分类选择代理增强类型

设置proxyTargetClass 演示
在这里插入图片描述
有接口实现,proxyTargetClass = false —> 符合第一条,期望代理实现为jdk代理,结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Aholic 冲冲冲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值