接着上一篇 https://blog.csdn.net/convict_eva/article/details/81084833
DefaultAopProxyFactory.createAopProxy() 方法生成AopProxy 代理对象。
AopProxy 有两个实现类 JdkDynamicAopProxy,CglibAopProxy。上一篇说的是JdkDynamicAopProxy,这里说 CglibAopProxy

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {//目录对象的classClass<?> targetClass = config.getTargetClass();//没有目标对象抛出异常if (targetClass == null) {throw new AopConfigException("TargetSource cannot determine target class: " +"Either an interface or a target is required for proxy creation.");}//targetClass 是接口类,使用 JDK来生成 Proxyif (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {return new JdkDynamicAopProxy(config);}//如果不是接口类,使用CGLIB 生成代理对象return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}
}

CglibAopProxy 也是AopProxy 的实现,CglibAopProxy 也是 ObjenesisCglibAopProxy 父类,所以入口方法就是 ObjenesisCglibAopProxy.getProxy()方法
这个方法在CglibAopProxy 实现的

CglibAopProxy.getProxy() 源码:

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isDebugEnabled()) {logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());}try {//从advised 中获取目标对象的类对象Class<?> rootClass = this.advised.getTargetClass();Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");Class<?> proxySuperClass = rootClass;if (ClassUtils.isCglibProxyClass(rootClass)) {//如果目标对象已经是CGLIB 生成代理对象(就是比较类名称中有 $$ 字符串),那么就取目标对象的父类作为目标对象的类proxySuperClass = rootClass.getSuperclass();Class<?>[] additionalInterfaces = rootClass.getInterfaces();for (Class<?> additionalInterface : additionalInterfaces) {this.advised.addInterface(additionalInterface);}}// Validate the class, writing log messages as necessary.// 打印出不能代理的方法名,CGLIB 是使用继承实现的,所以final , static 的方法不能被增强validateClassIfNecessary(proxySuperClass, classLoader);// Configure CGLIB Enhancer...//创建并配置 Enhancer,  Enhancer 是CGLIB 主要的操作类Enhancer enhancer = createEnhancer();if (classLoader != null) {enhancer.setClassLoader(classLoader);if (classLoader instanceof SmartClassLoader &&((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {enhancer.setUseCache(false);}}//配置超类,代理类实现的接口,回调方法等enhancer.setSuperclass(proxySuperClass);enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));// 获取callbasks Callback[] callbacks = getCallbacks(rootClass);Class<?>[] types = new Class<?>[callbacks.length];for (int x = 0; x < types.length; x++) {types[x] = callbacks[x].getClass();}// fixedInterceptorMap only populated at this point, after getCallbacks call aboveenhancer.setCallbackFilter(new ProxyCallbackFilter(this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));enhancer.setCallbackTypes(types);// Generate the proxy class and create a proxy instance.//通过 Enhancer 生成代理对象,并设置回调。 return createProxyClassAndInstance(enhancer, callbacks);}catch (CodeGenerationException | IllegalArgumentException ex) {throw new AopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() +": Common causes of this problem include using a final class or a non-visible class",ex);}catch (Throwable ex) {// TargetSource.getTarget() failedthrow new AopConfigException("Unexpected AOP exception", ex);}
}

总结:
CGLIB 通过 Enhancer 生成代理类的子类,并使用 DynamicAdvisedInterceptor 封装了增强方法
再把 DynamicAdvisedInterceptor 实现放入到callbacks 中就是通过对callbacks 的封装来完成aop的实现。
当调用代理对象的方法,会被 DynamicAdvisedInterceptor.intercept() 方法拦截。
具体怎么调用这个callbacks 的,我也不知道,猜测是生成代理类的实现有关。

CGLIB 的AOP拦截器实现:
DynamicAdvisedInterceptor 是一个 MethodInterceptor, 所以会调用他的 intercept() 方法

DynamicAdvisedInterceptor.intercept()源码:


@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {Object oldProxy = null;boolean setProxyContext = false;Object target = null;//目标对象TargetSource targetSource = this.advised.getTargetSource();try {if (this.advised.exposeProxy) {// Make invocation available if necessary.oldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...target = targetSource.getTarget();Class<?> targetClass = (target != null ? target.getClass() : null);//获取是拦截器链,和JDK中是一样的List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);//返回值Object retVal;// Check whether we only have one InvokerInterceptor: that is,// no real advice, but just reflective invocation of the target.if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {// We can skip creating a MethodInvocation: just invoke the target directly.// Note that the final invoker must be an InvokerInterceptor, so we know// it does nothing but a reflective operation on the target, and no hot// swapping or fancy proxying.//没有拦截器,就反射调用代理方法Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);retVal = methodProxy.invoke(target, argsToUse);}else {// We need to create a method invocation...//这个也是和jdk 动态代理实现是类似的,只是MethodInvocation实现类不同而已retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();}retVal = processReturnType(proxy, target, method, retVal);return retVal;}finally {if (target != null && !targetSource.isStatic()) {targetSource.releaseTarget(target);}if (setProxyContext) {// Restore old proxy.AopContext.setCurrentProxy(oldProxy);}}
}

总结:
从这个代码中可以看到,实现方式和jdk 动态代理是一样的,只是方法入口和MethodInvocation 实现类使用的不一样
JdkDynamicAopProxy 入口方法是动态代理的 invoke() 方法,CGLIB 使用的是 DynamicAdvisedInterceptor.intercept() 方法
JdkDynamicAopProxy 使用的MethodInvocation 是  ReflectiveMethodInvocation 子类,CGLIB 使用的是 CglibMethodInvocation。具体的实现参考上一篇就行。

spring--aop_2_源码分析之CglibAopProxy实现相关推荐

  1. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  2. Spring Cloud源码分析(二)Ribbon(续)

    因文章长度限制,故分为两篇.上一篇:<Spring Cloud源码分析(二)Ribbon> 负载均衡策略 通过上一篇对Ribbon的源码解读,我们已经对Ribbon实现的负载均衡器以及其中 ...

  3. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  4. Spring AOP 源码分析 - 筛选合适的通知器

    1.简介 从本篇文章开始,我将会对 Spring AOP 部分的源码进行分析.本文是 Spring AOP 源码分析系列文章的第二篇,本文主要分析 Spring AOP 是如何为目标 bean 筛选出 ...

  5. spring AOP源码分析(一)

    spring AOP源码分析(一) 对于springAOP的源码分析,我打算分三部分来讲解:1.配置文件的解析,解析为BeanDefination和其他信息然后注册到BeanFactory中:2.为目 ...

  6. 一步一步手绘Spring AOP运行时序图(Spring AOP 源码分析)

    相关内容: 架构师系列内容:架构师学习笔记(持续更新) 一步一步手绘Spring IOC运行时序图一(Spring 核心容器 IOC初始化过程) 一步一步手绘Spring IOC运行时序图二(基于XM ...

  7. 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现

    概述 我们知道 Spring Boot 能够创建独立的 Spring 应用,内部嵌入 Tomcat 容器(Jetty.Undertow),让我们的 jar 无需放入 Servlet 容器就能直接运行. ...

  8. 【Spring】Spring AOP源码分析-导读(一)

    文章目录 1.简介 2.AOP 原理 3.AOP 术语及相应的实现 3.1 连接点 - Joinpoint 3.2 切点 - Pointcut 3.3 通知 - Advice 3.4 切面 - Asp ...

  9. 视频教程-Spring底层源码分析-Java

    Spring底层源码分析 鲁班学院-子路老师曾就职于谷歌.天猫电商等多家互联网公司,历任java架构师.研发经理等职位,参与并主导千万级并发电商网站与后端供应链研发体系搭建,多次参与电商大促活动技术保 ...

  10. 【转】Spring AMQP 源码分析 01 - Impatient

    转自首夜盲毒预言家的文章 Spring AMQP 源码分析 01 - Impatient ### 准备 ## 目标 了解 Spring AMQP 核心代码 ## 前置知识 RabbitMQ 入门 ## ...

最新文章

  1. tensorflow1.14.0  包含了1.x和2.x内容,此后版本要求兼容该版本
  2. 1688 复杂业务场景下的 Serverless 提效实践
  3. C++的clone函数什么时候需要重载
  4. c语言全国计算机真题及答案,全国计算机C语言考试真题及答案.doc
  5. 冒泡排序(【CCF】NOI Online能力测试 提高组第二题)
  6. 一张图30分钟带你入门python-大数据时代来了!神级程序员一张图帮你梳理Python脉络,快速入门...
  7. 面试C++后台开发考察哪些问题?
  8. python中tell函数_PYTHON学习14.09:Python seek()和tell()函数详解
  9. wps office 2019中文版
  10. 5G - MEC(移动边缘计算)
  11. 利用wireshark分析Voip语音RTP协议
  12. svn服务器文件保存位置,Windows 部署SVN服务器
  13. 苹果xsmax有高通基带吗_苹果iPhone 12拆解:确认采用高通骁龙X55基带芯片
  14. [因果推断] 什么是因果推断(一)
  15. iphone 信号对应设备_如何访问iPhone的现场测试模式(并查看实际信号强度)
  16. 文科生学python简书_文科生Python教程(一)
  17. 记一次使用fiddler抓包抖音的挫折
  18. Windows中怎么下载桌面便签小工具 便签小工具简单使用教程
  19. 有没有好记一点,c++ ,set容器遍历方法?(看过来)
  20. 对象方法Dive into Python读书笔记3

热门文章

  1. python_6_13
  2. MD5工具类(java实现版)
  3. 谁是卧底 android,谁是卧底online
  4. 微信公众号获取用户头像昵称,用户信息
  5. android 夜间模式 遮罩,夜间模式(com.chenai.eyes) - 5.1.9 - 应用 - 酷安
  6. JavaScript鼠标拖动绘制方框实现选区
  7. Minitab 推出过程改善新的 Monte Carlo 仿真软件
  8. Docker容器不识别宋体等字体问题
  9. 31岁大叔自学android的一点感悟
  10. vtm编码划分_VTM代码学习(1)CU划分