怎么从代理对象拿回原始对象?代理类上找不到注解怎么办?代理和目标 equals 吗?多个切面叠加是几层代理?这篇在 Spring Framework 7.0.9 上逐项验证。
JDK 代理:getClass() = $Proxy2;AopUtils.getTargetClass = JdkTarget;AopProxyUtils.ultimateTargetClass = JdkTarget;ClassUtils.getUserClass = $Proxy2
((Advised) proxy).getTargetSource().getTarget() = JdkTarget;proxy == target ? false;isAopProxy(target) = false
CGLIB 代理:getClass() = CglibTarget·CGLIB;AopUtils.getTargetClass = CglibTarget;AopProxyUtils.ultimateTargetClass = CglibTarget;ClassUtils.getUserClass = CglibTarget
((Advised) proxy).getTargetSource().getTarget() = CglibTarget;proxy == target ? false;isAopProxy(target) = false
两层代理:最外层 → getTarget() 得到 $Proxy2(还是个代理:true);AopProxyUtils.getSingletonTarget(最外层) = $Proxy2;ultimateTargetClass = JdkTarget;AopUtils.getTargetClass = $Proxy2
getSingletonTarget 连续两次 → JdkTargetgetTargetClass、ultimateTargetClass、getTarget() 各有适用范围,多层代理要用 ultimate 系列。
CGLIB 代理 CglibTarget·CGLIB:pc.getAnnotation(Tag.class) = null;pc.isAnnotationPresent(Tag) = false
AnnotationUtils.findAnnotation(pc, Tag.class) = @Tag(on-class);AnnotatedElementUtils.findMergedAnnotation = @Tag(on-class);getAnnotation(AopUtils.getTargetClass(p)) = @demo.Main.Tag("on-class")
JDK 代理 $Proxy2:jc.getAnnotation(Tag.class) = null;findAnnotation(jc) = null;findAnnotation(AopUtils.getTargetClass(j)) = @Tag(on-class)代理类上直接 getAnnotation 会漏掉类注解,要用 findAnnotation 或目标类。
CGLIB 代理:p1.equals(p1) = true;p1.equals(target) = false;target.equals(p1) = false;p1.hashCode() == target.hashCode() ? false;p1.toString() 以 CglibTarget 开头?true JDK 代理:j1.equals(j1) = true;j1.equals(target) = false;j1.hashCode() == target.hashCode() ? false;HashSet 里放 target 再用 j1 查 contains = false
代理和目标不相等,混放在集合里会查不到。
同时有两个切面 A1、A2 和 @Async 作用在 CglibTarget 上:Bean 是代理?true;Advised.getAdvisors().length = 4;advisors = [AnnotationAsyncExecutionInterceptor, ExposeInvocationInterceptor, AspectJAroundAdvice, AspectJAroundAdvice]
getTarget() = CglibTarget(是代理:false);说明多个切面和 @Async 被合并进了同一个代理对象的拦截链,不是一层套一层多个切面与 @Async 合并进同一个代理的拦截器链。