【JavaEE进阶】 Spring AOP源码简单剖析

文章目录

  • 🍃前言
  • 🍀Spring AOP源码剖析
  • ⭕总结

🍃前言

前面的博客中,博主对代理模式进行了一个简单的讲解,接下来博主将对Spring AOP源码进行简单剖析,使我们对Spring AOP了解的更加深刻。

🍀Spring AOP源码剖析

Spring AOP 主要基于两种⽅式实现的:JDK 及 CGLIB 的⽅式

Spring对于AOP的实现,基本上都是靠AnnotationAwareAspectJAutoProxyCreator 去完成⽣成代理对象的逻辑在⽗类 AbstractAutoProxyCreator 中

相关源码与注解如下:

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,@Nullable Object[] specificInterceptors, TargetSource targetSource) {if (this.beanFactory instanceof ConfigurableListableBeanFactory) {AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory)this.beanFactory, beanName, beanClass);}
//创建代理⼯⼚ProxyFactory proxyFactory = new ProxyFactory();proxyFactory.copyFrom(this);
/*** 检查proxyTargetClass属性值,spring默认为false* proxyTargetClass 检查接⼝是否对类代理, ⽽不是对接⼝代理* 如果代理对象为类, 设置为true, 使⽤cglib代理*/if (!proxyFactory.isProxyTargetClass()) {
//是否有设置cglib代理if (shouldProxyTargetClass(beanClass, beanName)) {
//设置proxyTargetClass为true,使⽤cglib代理proxyFactory.setProxyTargetClass(true);} else {
/*** 如果beanClass实现了接⼝,且接⼝⾄少有⼀个⾃定义⽅法,则使⽤JDK代理* 否则CGLIB代理(设置ProxyTargetClass为true )* 即使我们配置了proxyTargetClass=false, 经过这⾥的⼀些判断还是可能会将其设为true*/evaluateProxyInterfaces(beanClass, proxyFactory);}}Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);proxyFactory.addAdvisors(advisors);proxyFactory.setTargetSource(targetSource);customizeProxyFactory(proxyFactory);proxyFactory.setFrozen(this.freezeProxy);if (advisorsPreFiltered()) {proxyFactory.setPreFiltered(true);}
// Use original ClassLoader if bean class not locally loaded in overridingclass loader
ClassLoader classLoader = getProxyClassLoader();if (classLoader instanceof SmartClassLoader && classLoader !=beanClass.getClassLoader()) {classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();}
//从代理⼯⼚中获取代理return proxyFactory.getProxy(classLoader);
}

代理工⼚有⼀个重要的属性:proxyTargetClass,默认值为false.

也可以通过程序设置

proxyTargetClass⽬标对象代理⽅式
false实现了接⼝jdk代理
false未实现接⼝(只有实现类)cglib代理
true实现了接⼝cglib代理
true未实现接⼝(只有实现类)cglib代理

可以通过 @EnableAspectJAutoProxy(proxyTargetClass = true) 来设置

需要注意的是:

  • Spring Boot 2.X开始,默认使⽤CGLIB代理,可以通过配置项 spring.aop.proxy-target-class=false 来进⾏修改,设置默认为jdk代理
    SpringBoot设置 @EnableAspectJAutoProxy ⽆效,因为Spring Boot默认使⽤AopAutoConfiguration进⾏装配
@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {ApplicationContext context =SpringApplication.run(DemoApplication.class, args);
/*** HouseProxy houseProxy = context.getBean(HouseProxy.class);* 设置spring.aop.proxy-target-class=true cglib代理, 运⾏成功* 设置spring.aop.proxy-target-class=false jdk代理, 运⾏失败, 不能代理类* 因为 HouseProxy 是⼀个类, ⽽不是接⼝, 需要修改为* HouseSubject houseProxy = (HouseSubject)context.getBean("realHouseSubject")**/HouseProxy houseProxy = context.getBean(HouseProxy.class);
//HouseSubject houseProxy = (HouseSubject)context.getBean("realHouseSubject");//正确运⾏System.out.println(houseProxy.getClass().toString());}
}

注意:使⽤context.getBean()需要添加注解,使HouseProxy,RealHouseSubject被Spring管理测试AOP代理,需要把这些类交给AOP管理(⾃定义注解或使用@Aspect)

我们再看以下代理⼯⼚的代码

public class ProxyFactory extends ProxyCreatorSupport {//...代码省略
//获取代理public Object getProxy(@Nullable ClassLoader classLoader) {
//分两步 先createAopProxy,后getProxyreturn createAopProxy().getProxy(classLoader);}protected final synchronized AopProxy createAopProxy() {if (!this.active) {activate();}return getAopProxyFactory().createAopProxy(this);}
//...代码省略
}

createAopProxy的实现在DefaultAopProxyFactory中

public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {//...代码省略@Overridepublic AopProxy createAopProxy(AdvisedSupport config) throwsAopConfigException {
/*** 根据proxyTargetClass判断* 如果⽬标类是接⼝, 使⽤JDK动态代理* 否则使⽤cglib动态代理*/if (!NativeDetector.inNativeImage() &&(config.isOptimize() || config.isProxyTargetClass() ||hasNoUserSuppliedProxyInterfaces(config))) {Class<?> targetClass = config.getTargetClass();if (targetClass == null) {throw new AopConfigException("TargetSource cannot determinetarget class: " +"Either an interface or a target is required for proxycreation.");}if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) ||ClassUtils.isLambdaClass(targetClass)) {return new JdkDynamicAopProxy(config);}return new ObjenesisCglibAopProxy(config);}else {return new JdkDynamicAopProxy(config);}}
//...代码省略
}

接下来就是创建代理了

JDK动态代理

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler,Serializable {//...代码省略@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {if (logger.isTraceEnabled()) {logger.trace("Creating JDK dynamic proxy: " +this.advised.getTargetSource());}return Proxy.newProxyInstance(determineClassLoader(classLoader),this.proxiedInterfaces, this);}
//...代码省略
}

CGLIB动态代理

class CglibAopProxy implements AopProxy, Serializable {//...代码省略@Overridepublic Object getProxy(@Nullable ClassLoader classLoader) {//...代码省略
// Configure CGLIB Enhancer...Enhancer enhancer = createEnhancer();
// Generate the proxy class and create a proxy instance.return createProxyClassAndInstance(enhancer, callbacks);}
//...代码省略
}

以上就是对Spring AOP源码的一个简单剖析。

⭕总结

关于《【JavaEE进阶】 Spring AOP源码简单剖析》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/714472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 简单

1. 两数之和 两数之和 方法1&#xff1a;暴力枚举 两次for 循环&#xff0c;记录索引和值&#xff0c;找到合适的值然后返回 方法2&#xff1a;使用哈希表 第一次for循环的时候&#xff0c;就可以使用哈希表记录key的value&#xff0c;可以实现时间复杂度是1&#xff0c;要分…

【前端素材】推荐优质后台管理系统网页Highdmin平台模板(附源码)

一、需求分析 1、系统定义 后台管理系统是一种用于管理和控制网站、应用程序或系统的管理界面。它通常被设计用来让网站或应用程序的管理员或运营人员管理内容、用户、数据以及其他相关功能。后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;通常由管理员使…

express+mysql+vue,从零搭建一个商城管理系统7--文件上传,大文件分片上传

提示&#xff1a;学习express&#xff0c;搭建管理系统 文章目录 前言一、安装multer&#xff0c;fs-extra二、新建config/upload.js三、新建routes/upload.js四、修改routes下的index.js五、修改index.js六、新建上传文件test.html七、开启jwt验证token&#xff0c;通过login接…

Vue.js+SpringBoot开发开放实验室管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实验管理模块2.4 实验设备模块2.5 实验订单模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示五、样例代码5.1 查询实验室设备5.2 实验放号5.3 实验预定 六、免责说明 一、摘…

vue3的router

需求 路由组件一般放在&#xff0c;pages或views文件夹, 一般组件通常放在component文件夹 路由的2中写法 子路由 其实就是在News组件里面&#xff0c;再定义一个router-view组件 他的子组件&#xff0c;机会渲染在router-view区域 路由传参 <RouterLink :to"/news…

解决导入项目后在idea中不显示的问题

问题&#xff1a; 今天下午重新打开寒假之前负责的项目&#xff0c;发现打不开了&#xff0c; 从master拉取最新代码到我的分支&#xff0c;发现我的分支上显示就是这样子&#xff0c;无论怎么更新代码都不行。 原因&#xff1a; 在上一次上传代码的时候&#xff0c;我把我分…

leetcode括号生成

题目描述 解题思路 首先看到题目&#xff0c;一开始是并没有思路的。这时候可以在纸上进行演算一下结果。当只有一对括号的时候&#xff0c;我们可以得知结果[“()”],当有两对括号的时候&#xff0c;我们可以发现&#xff0c;括号在第一个基础上&#xff0c;要么在括号内部出…

静态时序分析:SDC约束命令set_case_analysis详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 目录 指定值 指定端口/引脚列表 简单使用 set_case_analysis命令用于对电路进行特定模式的设定&#xff0c;例如对于一个工作在正常模式下的芯片&#xff0c;…

HTML5新特性:为Web带来的翻天覆地变化

随着互联网的发展&#xff0c;HTML5作为Web开发的重要里程碑&#xff0c;为我们带来了一系列令人兴奋的新特性和功能。本文将带领大家探索HTML5的新特性&#xff0c;揭示其对Web技术的巨大影响。 一、介绍 HTML5作为HTML的最新版本&#xff0c;不仅强化了网页结构与内容&#…

Android 解决引入的三方库中类名冲突问题

参考&#xff1a; Android开发——如何解决三方库中的类名冲突问题_android 类冲突-CSDN博客 Android 解决 jar/aar 包类名冲突 - 简书 实操步骤 1.提前安装好unzip-5.51-bin&#xff0c;proguard-7.4.0&#xff0c;jarjar-1.4软件 2.解压包名冲突的 AAR 文件 进入到需要修…

reach功能的使用

1.reach添加后 1.reach添加后2 2.拷贝reach最后一帧的动作 3.删除reach(注意画选时如果reach延长不能直接删否则以前的动画也会删掉&#xff0c;要缩短reach后再删另外这两个灰原点也要删掉否则影响后边新加clip的对齐会出现乱七八糟的事情) 4.删除reach后&#xff0c;光标移到…

收藏:数据防泄漏系统推荐,数据防泄漏系统有哪些?

一金融机构在近期发生了一起数据泄露事件。 经过调查&#xff0c;发现是由于一名员工将包含客户敏感信息的文件通过电子邮件发送给了未经授权的第三方。 这一事件导致客户数据泄露&#xff0c;给该机构带来了严重的声誉损失和信任危机。 这一案例凸显了数据防泄漏系统的重要性…

Neo4j aura 官方网站快速入门新手教精读-从官方教程学习知识图谱

Neo4j 官方网站快速入门新手教精读 本文旨在为Neo4j新手提供一份全面的入门指南。除了基础的文本解释&#xff0c;我在里面还插入了每一步骤的详细截图或者自己画的图&#xff0c;从官方了解知识肯定比自己乱看要权威一些&#xff0c;有看不懂的不要纠结了解大概意思即可&#…

Java中心校智慧校园智慧班牌物联网平台源码

目录 智慧班牌 班牌首页 班级信息 课表信息 视频 图片 进离校管理 人脸登录页 学生个人中心 请假管理 成绩管理 家长留言 学生绑卡 学生评价 系统设置 通知管理 值日管理 倒计时 班级德育 班牌模式 1.课堂授课模式 2.家长会签到模式 3.考场模式 4.班级…

React富文本编辑器开发(一)

这是一个系统的完整的教程&#xff0c;每一节文章的内容都很重要。这个教程学完后自己可以开发出一个相当完美的富文本编辑器了。下面就开始我们今天的内容&#xff1a; 安装 是的&#xff0c;我们的开发是基于Slate的开发基础&#xff0c;所以要安装它&#xff1a; yarn ad…

【贪心算法】Leetcode 122. 买卖股票的最佳时机 II

【贪心算法】Leetcode 122. 买卖股票的最佳时机 II 122. 买卖股票的最佳时机 II贪心算法&#xff1a;整体利润拆为每天的利润&#xff0c;只收集每天的正利润 122. 买卖股票的最佳时机 II ---------------&#x1f388;&#x1f388;122. 买卖股票的最佳时机 II 题目链接&…

【Excel PDF 系列】EasyExcel + iText 库实现 Excel 转换 PDF

你知道的越多&#xff0c;你不知道的越多 点赞再看&#xff0c;养成习惯 如果您有疑问或者见解&#xff0c;欢迎指教&#xff1a; 企鹅&#xff1a;869192208 文章目录 前言转换前后效果引入 pom 配置代码实现定义 ExcelDataVo 对象主方法EasyExcel 监听器 前言 最近遇到生成 …

图论 - 最小生成树(Prime、Kruskal)

文章目录 前言Part 1&#xff1a;Prim算法求最小生成树1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 Part 2&#xff1a;Kruskal算法求最小生成树1.题目描述输入格式输出格式数据范围输入样例输出样例 2.算法 前言 本篇博客介绍两种求最小生成树的方法&#xff…

辽宁博学优晨教育视频:引领安全可靠的学习新风尚

在数字化时代&#xff0c;随着信息技术的飞速发展&#xff0c;线上教育已成为越来越多人提升自我、拓宽视野的重要选择。辽宁博学优晨教育视频凭借其安全可靠的特质&#xff0c;在众多在线教育平台中脱颖而出&#xff0c;成为广大学子信赖的学习伙伴。 一、辽宁博学优晨教育视频…

MagiskHideProps 使用 props 开启 android 手机的 ro.debuggable =1 的方法

因为 CDSN 一直不给对旧的文章&#xff08;特别是边幅比较长的文章&#xff09;一直都无法修改&#xff0c;保存&#xff0c;重新发布 一直都是操作超时 我这里是补全 这边文章中 unity shader - 圣斗士星矢 人物 shader 还原 - GPA 抓帧提取资源、shader&#xff0c;ROOT权…