JDK代理 | CGLB代理 |
目标类是接口(/实现)类 或代理类 或启用GraalVM Native Image编译
| 重写代理接口 或默认为CGLB代理 或optimize标志已设置(增强化策略)
默认为CGLB代理时 实现类会使用默认配置CGLB代理 |
两者区别:
-
JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
-
CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
@Aspect 此注解创建代理的方式也是采用此方式
------此文对应下图观看
当默认为JDK代理时,如果目标类是实现类,此时默认ProxyTargetClass为false 此时无指定代理接口也无增强化会进入if{}中导致后续使用了JDK代理,后续如果不是接口类(此接收对象必须还要是实现类实现的接口类)接收此代理对象,则会抛出异常。
(问题原因:JDK代理只是接口代理,此时的代理对象是此实现类实现的接口类,JDK动态代理只提供接口的代理,不支持类的代理。)
(解决方案:默认使用CGLB代理或使用此实现类实现的接口类接收此此代理对象--所以SpringBoot2.0开始默认使用CGLB代理防止此错误发生)。
当默认为CGLB代理时,如果目标类是实现类,此时默认ProxyTargetClass为true, 此时会进else{}中,经过判断此目标类不是接口类也不是代理类会使用CGLB代理。

NativeDetector--这个我照搬api上的,我不想了解它有点变态,有兴趣的伙伴可以自己去了解
用于检测GraalVM本机映像环境的公共委托。
需要使用本机映像编译器标志以允许在生成时删除代码
-H:+InlineBeforeAnalysis
inNativeImage()
如果在映像生成上下文中或在映像运行时期间调用,则返回true。否则false
ProxyTargetClass 使用默认配置 默认JDK代理则为false 默认CGLB代理为true,
(注意:此时默认为JDK代理时,当使用isProxyTargetClass()方法时会检测此目标类是否是接口类或代理类如不是则默认为false,反之会将其变为true---类验证检查)
配置:
Spring--XML

SpringBoot-注解

isOptimize()是否设置增强化策略(可配置---这个磨不透,也没往下磨有兴趣的可以全程跟踪源码走一次看看)
optimize用来标记是否需要对代理对象采取性能优化措施,默认值为false。
如果将optimize设置为true,那么在生成代理对象之后,如果对代理配置进行了修改,已经创建的代理对象也不会获取修改之后的代理配置。
使用Spring当前的代理选项,此标志有效地强制执行CGLIB代理(类似于setProxyTargetClass(布尔值)),
但没有任何类验证检查(对于最终方法等)。
hasNoUserSuppliedProxyInterfaces()是否指定代理接口
( 如果直接继承SpringProxy相关接口,重写里面的方法,那么就会采用默认自己写的代理方法,而不会使用SpringAop提供的方法)

使用与借鉴以下大佬文章内容:
Spring-Framework API地址: