码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【Spring 源码】AOP 的加载原理(二)


    【Spring 源码】AOP 的加载原理(二)


    文章目录

    • 【Spring 源码】AOP 的加载原理(二)
    • 一、选择创建策略
      • 1. JDK 动态代理
        • 【1】获取被代理的接口
        • 【2】JDK 动态代理主要处理方法
        • 【3】将 Advisors 封装成调用链
        • 【4】Advisor 的实际处理方法
      • 2. CGLib 动态代理
        • 【1】获取代理创建的 Bean
        • 【3】CGLib 主要处理方法


    一、选择创建策略

    主要代码:DefaultAopProxyFactory#createAopProxy()

    在之前讲到 DefaultAopProxyFactory 是默认的创建代理的工厂类,会根据传入的被代理类来选择不同的创建策略。

    @Override
    public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
       
    	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
       
    		Class<?> 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.");
    		}
    		// 如果是接口或者是 Proxy 类型的 Bean 要创建 JDK 动态代理
    		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
       
    			return new JdkDynamicAopProxy(config);
    		}
    
    		// 其他情况会创建 CGLib 动态代理
    		return new ObjenesisCglibAopProxy(config);
    	}
    	else {
       
    		// 使用 JDK 动态代理
    		return new JdkDynamicAopProxy(config);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    1. JDK 动态代理

    JDK 动态代理

    【1】获取被代理的接口

    主要代码:JdkDynamicAopProxy#getProxy()

    在这个过程中,主要是通过 AopProxyUtils.completeProxiedInterfaces() 进行被代理接口的筛选,在 Java 中,我们都知道一个类只能继承一个父类,但是可以实现多个接口,所以要找到被代理的接口需要做一堆工作。

    @Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
       
    	if (logger.isTraceEnabled()) {
       
    		logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    	}
    	
    	// 获取需要代理的接口
    	Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    	
    	// 找 EqualsAndHashCode 方法
    	findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    	
    	// JDK 动态代理的获取目标类的主要方法
    	return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    【2】JDK 动态代理主要处理方法

    主要代码:JdkDynamicAopProxy#invoke()

    在方法中,会发现 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 这么一行方法,这边主要是使用了责任链模式对 Advisors 进行封装成链,以便后续继续使用。

    @Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       
    	Object oldProxy = null;
    	boolean setProxyContext = false;
    
    	TargetSource targetSource = this.advised.targetSource;
    	Object target = null;
    
    	try {
       
    		// 目标未实现 equals 方法
    		if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
       
    			return equals(args[0]);
    		}
    		// 目标未实现 hashCode 方法
    		else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
       
    			return hashCode();
    		}
    		else if (method.getDeclaringClass() == DecoratingProxy.class) {
       
    			return AopProxyUtils.ultimateTargetClass(this.advised);
    		}
    		// 直接反射调用
    		else if (!this.advised.opaque && method.getDeclaringClass
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    《Java 并发编程实战》—— Java内存模型:看Java如何解决可见性和有序性问题
    C#,二分图(Bipartite Graph)的霍普克罗夫特-卡普(Hopcroft Karp)最大匹配算法与源程序
    高频更新使用sse好还是WebSocket
    CH341 USB总线转接芯片
    渗透测试流程之DVWA漏洞靶场部署
    JUC工具类_CyclicBarrier与CountDownLatch
    Pop!_OS 21.10升级22.04失败记录
    Go语言学习笔记——使用swagger生成api接口文档
    element-ui组件输入框之放大镜(搜索图标)
    人保爱无忧易核版重疾险怎么样?好不好?
  • 原文地址:https://blog.csdn.net/weixin_41645142/article/details/126879484
  • 最新文章
  • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
    用 Hashids 优雅解决 C 端自增 ID 暴露问题
    V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
    LLVM Pass快速入门(四):代码插桩
    milkup:桌面端 markdown AI续写和即时渲染
    基于项目工程构建SBOM(软件物料清单)的研究
    鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
    .NET 中如何快速实现 List 集合去重?
    扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
    浅谈数据访问层
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号