Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题
Spring AOP底层的动态代理实现有两种方式:一种是JDK动态代理,另一种是CGLib动态代理。
JDK动态代理
JDK 1.3版本以后提供了动态代理,允许开发者在运行期创建接口的代理实例,而且只能为接口创建代理实例。
如果被代理目标没有接口那么Spring也无能为力,Spring通过Java的反射机制生成被代理接口的新的匿名实现类。
JDK动态代理具体实现原理:
通过实现
InvocationHandlet接口创建自己的调用处理器;通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理;
通过反射机制获取动态代理类的构造函数,其唯一参数类型就是调用处理器接口类型;
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数参入;
CGLib动态代理
CGLib 全称 Code Generation Library,是一个强大的高性能字节码生成类库,可以实现运行期动态扩展Java类。
Spring在运行期采用CGLib的字节码技术为类创建一个子类,并在子类中拦截所有父类方法的调用,织入横切逻辑实现AOP面向切面编程。
注意事项
如果被代理的对象实现了接口,那么Spring默认会使用JDK动态代理,否则会强制使用CGLib实现动态代理(如果被代理的类被final关键字所修饰,那么代理会失败)
关于两者的性能,JDK动态代理所创建的代理对象,在1.8以前的版本中性能并不高,最新版本中性能得到了很大的提升,和CGLib相差不大。
Spring Boot中无法正常启用JDK动态代理的问题
关于Spring的默认动态代理模式,官方文档中显示是JDK动态代理,但Spring Boot 2.2中发现即使强制指定@EnableAspectJAutoProxy(proxyTargetClass = false) ,生成的代理类依然显示$EnhancerBySpringCGLIB。
在DefaultAopProxyFactory中发现isProxyTargetClass被指定为强制代理目标类,所以会采用ObjenesisCglibAopProxy创建代理。
最后跟踪到ValidationAutoConfiguration中的一个Bean方法中,主动读取了环境变量spring.aop.proxy-target-class,而且默认值是true。
问题点算是找到了,不过这里只是一个函数校验的处理器,竟然会强制读取魔法配置,有些莫名其妙...手工添加配置后JDK代理恢复正常。
@Bean
@ConditionalOnMissingBean
public static MethodValidationPostProcessor methodValidationPostProcessor(Environment environment, @Lazy Validator validator) {
MethodValidationPostProcessor processor = new MethodValidationPostProcessor();
boolean proxyTargetClass = environment.getProperty("spring.aop.proxy-target-class", Boolean.class, true);
processor.setProxyTargetClass(proxyTargetClass);
processor.setValidator(validator);
return processor;
}
Spring AOP动态代理实现,解决Spring Boot中无法正常启用JDK动态代理的问题的更多相关文章
- [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.
前言: 在上一篇中: [Spring框架]Spring AOP基础入门总结一. 中 我们已经知道了一个Spring AOP程序是如何开发的, 在这里呢我们将基于AspectJ来进行AOP 的总结和学习 ...
- 重学 Java 设计模式:实战代理模式「模拟mybatis-spring中定义DAO接口,使用代理类方式操作数据库原理实现场景」
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 难以跨越的瓶颈期,把你拿捏滴死死的! 编程开发学习过程中遇到的瓶颈期,往往是由于看不 ...
- 解决 Maven 项目中找不到 jdk 的 tools.jar 文件的办法(多数情况下适用)
<dependency> <groupId>jdk.tools</groupId> <artifactId>jdk.tools</artifact ...
- Spring系列(四):Spring AOP详解
一.AOP是什么 AOP(面向切面编程),可以说是一种编程思想,其中的Spring AOP和AspectJ都是现实了这种编程思想.相对OOP(面向过程编程)来说,提供了另外一种编程方式,对于OOP过程 ...
- Spring Aop(一)——Aop简介
转发地址:https://www.iteye.com/blog/elim-2394629 1 Aop简介 AOP的全称是Aspect Oriented Programming,翻译成中文是面向切面编程 ...
- 【总结】spring aop
1.aop简介 AOP的全称是Aspect Oriented Programming,面向切面编程.它的主要思想是在程序正常执行的某一个点切进去加入特定的逻辑.AOP框架中对AOP支持最完整的是Asp ...
- Spring AOP详解 、 JDK动态代理、CGLib动态代理
AOP是Aspect Oriented Programing的简称,面向切面编程.AOP适合于那些具有横切逻辑的应用:如性能监测,访问控制,事务管理以及日志记录.AOP将这些分散在各个业务逻辑中的代码 ...
- Spring AOP中的动态代理
0 前言 1 动态代理 1.1 JDK动态代理 1.2 CGLIB动态代理 1.2.1 CGLIB的代理用法 1.2.2 CGLIB的过滤功能 2 Spring AOP中的动态代理机制 2.1 ...
- 【转载】Spring AOP详解 、 JDK动态代理、CGLib动态代理
Spring AOP详解 . JDK动态代理.CGLib动态代理 原文地址:https://www.cnblogs.com/kukudelaomao/p/5897893.html AOP是Aspec ...
随机推荐
- VUE+ElementUI 搭建后台项目(一)
前言 之前有些过移动端的项目搭建的文章,感觉不写个pc端管理系统老感觉少了点什么,最近公司项目比较多,恰巧要做一个申报系统的后台管理系统,鉴于对vue技术栈比较熟悉,所以考虑还是使用vue技术栈来做: ...
- javascript之DOM(二Document对象)
javascript通过Document类型来表示文档.在浏览器中document是HTMLDocument对象(继承自Document)的一个实例,表示整个html页面.而且在浏览器中documen ...
- 目标检测论文解读6——SSD
背景 R-CNN系列算法检测速度不够快,YOLO v1检测准确率较低,而且无法检测到密集目标. 方法 SSD算法跟YOLO类似,都属于one stage的算法,即通过回归算法直接从原图得到预测结果,为 ...
- Kth Minimum Clique(2019年牛客多校第二场D题+k小团+bitset)
目录 题目链接 题意 思路 代码 题目链接 传送门 题意 找第\(k\)小团. 思路 用\(bitset\)来标记每个结点与哪些结点直接有边,然后进行\(bfs\),在判断新加入的点与现在有的点是否都 ...
- vuex中mapGetters的使用及简单实现原理
一.项目中的mapGetters在Vue项目的开发过程中必然会使用到vuex,对vue项目公用数据进行管理,从而解决组件之间数据相互通信的问题,如果不使用vuex,那么一些非父子组件之间的数据通信将会 ...
- 201871010102-常龙龙《面向对象程序设计(java)》第二周学习总结
项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.com/nwnu-daizh/p ...
- MySQL | MySQL 数据库系统(一)
## 1.什么是 MySQL 数据库? MySQL 数据库是一个关系型数据库管理系统,是服务器领域中受欢迎的开源数据库系统,目前有 Oracle 公司主要负责运营与维护: ## 2.MySQL 数据库 ...
- 面向对象高级B(元类)
元类 python一切皆对象,类实际上也是一个一个对象 类是一个对象,那他一定是由一个类实例化得到,这个类就叫元类 如何找元类 class Person: def __init__(self, nam ...
- VIJOS-P1199 核弹危机
JDOJ 1347: VIJOS-P1199 核弹危机 题目传送门 Description shibowen和ganggang正在玩红警,可不料shibowen造出了核弹正要发射......(gang ...
- 【myBatis】Error evaluating expression ‘’. Return value () was not iterable.
被遍历的foreach不是数组或者集合