Spring Boot 中是使用 JDK Proxy 动态代理还是 CGLib ?

1. Spring Boot 中是使用 JDK Proxy 动态代理还是 CGLib ?

        首先我们知道在 Spring 里面,动态代理的底层,默认使用的是 JDK Proxy 代理,这一点在官方文档有具体的说明:

        既然 Spring 中的动态代理默认使用 JDK Proxy,那么在 Spring Boot 中是否也是使用 JDK Proxy 呢 ?

答案是否,Spring Boot 的动态代理默认使用的是 CGLib

这一点在 spring-configuration-metadata.json 文件中有体现 >>

我们带着疑惑来看下面这个案例,看看 Spring Boot 中的动态代理是否真的使用了 CGLib ?

Controller:

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate IUserService userService;@RequestMapping("/sayhi")public void sayHi() {userService.sayHi();}
}

service 接口:

public interface IUserService {void sayHi();
}

ServiceImpl:

@Service
public class UserServiceImpl implements IUserService {@Overridepublic void sayHi() {}
}

使用 AOP 拦截目标方法:

@Aspect // 切面
@Component
public class LoginAspect {@Before("execution(* com.example.demo.service.impl.UserServiceImpl.*(..))")public void doBefore(JoinPoint joinPoint) {System.out.println("拦截 sayHi 方法:" +joinPoint.getSignature().getName());}
}

打断点,启动项目访问 sayhi 接口:

此时,我们发现 Spring Boot 动态代理底层确实使用了 CGLib 来实现。

🍁【思考一】

        我们都知道使用 CGLIb 实现代理,被代理类是不能被 final 修饰的,因为 CGLib 是通过生成目标类的子类来保证代理类和被代理类的方法名一致,从而实现动态代理的,那如果上述被代理类使用 final 修饰,再次运行程序时,它底层是改成 JDK Proxy 代理呢 ?还是程序执行报错呢 ?

// 被代理类
@Service
public final class UserServiceImpl implements IUserService {@Overridepublic void sayHi() {}
}

运行程序时报错:错误信息也很明显

【结论一】 

        Spring Boot 使用动态代理时,底层默认使用的是 CGLib,并且是强制性的,一旦目标类被 final 修饰了,那么程序运行时就会报错,而不是使用 JDK Proxy 来完成代理。

如果想要让 Spring Boot 动态代理使用 JDK Proxy 也是可以的,不过需要配置两个属性:

# 是否启用 AOP
Spring.aop.auto=true
# 代理方式:设置为 true 表示强制使用 CGLib,false 表示使用 JDK
Spring.aop.proxy-target-class=false

properties 文件中配置了这两属性,再次打断点查看(确实使用了 JDK):

此时就算被代理类使用 final 修饰了,也可以被 JDK 代理。

🍁【思考二】

        我们都知道 JDK Proxy 实现的动态代理,被代理类是需要实现一个接口来保证代理类和被代理类的方法名一致,从而实现动态代理的,假设使用 JDK Proxy 动态代理时,目标类没有实现接口,程序运行时,是报错呢 ? 还是使用 CGLib 实现代理 ?

// 被代理类
@Service
public class UserServiceImpl {public void sayHi() {}
}

此时,在 Controller 中注入 UserServiceImpl,打断点查看(这次使用了 CGLib):

【最终结论】 

1.Spring Boot 默认的动态代理是 CGLib,并且是强制性的,加上 final,项目启动就会报错;

2.想让 Spring Boot 使用 JDK 代理,需要在配置文件中开启 AOP,并把代理方式的属性设为 false,才能使用 JDK 代理;

3.Spring Boot 使用 JDK 代理时,目标类如果没有实现接口,程序运行时,会使用 CGLib 来实现代理。

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

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

相关文章

Nginx详解之Nginx高级配置

Nginx详解之Nginx高级配置 1、网页的状态页2、Nginx第三方模块2.1echo模块 3、变量3.1内置变量3.2自定义变量 4、自定义访问日志4.1 自定义访问日志的格式4.2自定义json 格式日志 5、Nginx压缩功能(重要)6、https 功能6.1Nginx的HTTPS工作原理的详解6.2启…

电脑每次开机杀毒软件报iusb3mon.exe病毒已清除,电脑中病毒iusbmon杀毒办法,工具杀毒

不知道什么时候开始,我电脑C盘的系统数据存储文件夹programdata 不知不觉就没了,找不到了 programdata文件夹为存储系统数据文件的,这个文件不见了,而且我打开了显示隐藏文件和文件夹还是没有显示 然后我重启电脑,杀毒…

VueX 与Pinia 一篇搞懂

VueX 简介 Vue官方:状态管理工具 状态管理是什么 需要在多个组件中共享的状态、且是响应式的、一个变,全都改变。 例如一些全局要用的的状态信息:用户登录状态、用户名称、地理位置信息、购物车中商品、等等 这时候我们就需要这么一个工…

数据结构:线性表之-顺序表

目录 1.线性表概念 1.1 什么是顺序列表 1.2 线性表 2.顺序表实现 将有以下功能: 详细过程 顺序表的动态存储 顺序表初始化 尾插 扩容 头插 更改后的尾插 尾删 头删 打印 释放内存 优化顺序表 (任意位置插入删除) 优化后的头插尾插 优化后的头删尾…

java八股文面试[数据库]——数据库三范式

什么是范式? 范式是数据库设计时遵循的一种规范,不同的规范要求遵循不同的范式。 最常用的三大范式 第一范式(1NF):属性不可分割,即每个属性都是不可分割的原子项。(实体的属性即表中的列) 理解:一个列不能包含两个数…

新能源技术是实现碳达峰碳中和的必然路径

在绿色经济发展的时代背景之下,光伏屋顶瓦顺势而生。集发电、环保功能于一体的光伏屋顶瓦,让每一栋建筑都能成为一座绿色发电站,实现建筑用电自给,有效降低建筑能耗,极大的推动生态建筑和生态城市的发展。 太阳能光伏瓦…

SLAM从入门到精通(基础数学)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 不可否认,slam中的有一部分内容来自于数学。但是,我们在学习使用的过程中,也不用纠结于整个数学的推导过程&…

36、springboot --- 对 tomcat服务器 和 undertow服务器 配置访客日志

springboot 配置访客日志 ★ 配置访客日志: 访客日志: Web服务器可以将所有访问用户的记录都以日志的形式记录下来,主要就是记录来自哪个IP的用户、在哪个时间点、访问了哪个资源。 Web服务器可将所有访问记录以日志形式记录下来&#xff…

nuxt3+ts+vue3的ssr项目总结

目录 一、什么是SSR、SEO、SPA,它们之间的关系又是怎样的。 二、VUE做SSR的几种方法 1、插件prerender-spa-plugin 2、VUE开启SSR渲染模式 3、使用NUXT框架 三、NUXT3VUE3TS (一)基本配置 1、文件夹介绍 assets components pages…

QT 界面相关操作

1> 创建自定义类时需要指定父类 2> 第一个界面的相关操作 #include "widget.h" #include<iostream> //printf #include<QDebug> //qDebuf #include<QIcon> //图标的头文件 using namespace std; //coutWidget::Widget(QWidget *…

1.RTKLIB环境配置和调试

1.源码下载 下载链接&#xff1a;rtklib 注&#xff1a;2.4.2 p13为稳定版本&#xff08;标识p代表稳定版本&#xff09;&#xff0c;2.4.3 b34为最新实验版本&#xff08;标识b&#xff09;。点击2.4.3 b34 的Source Programs and Data 链接下载源码。 2.环境配置 **集成…

尚硅谷SpringMVC

五、域对象共享数据 1、使用ServletAPI向request域对象共享数据 首页&#xff1a; Controller public class TestController {RequestMapping("/")public String index(){return "index";} } <!DOCTYPE html> <html lang"en" xmln…

【ACM出版】第四届人工智能与计算工程国际学术会议(ICAICE 2023)

ACM出版|第四届人工智能与计算工程国际学术会议 The 4th International Conference on Artificial Intelligence and Computer Engineering 为了在人工智能技术应用与计算工程领域进一步的探索&#xff0c;与国内外学界和业界相关人员交流新问题、新发现、新成果、新应用&…

eureka迁移到nacos--双服务中心注册

服务注册中心的迁移有多种方式&#xff0c;官网使用nacos sync&#xff0c;还有民间开发的双注册中心组件eureka-nacos-proxy&#xff0c;但是我用了不太顺利&#xff0c;所以用的是阿里巴巴的双注册中心组件edas-sc-migration-starter spring boot&#xff1a;2.5.3 引入依赖 …

Springboot集成Docker并将镜像推送linux服务器

案例使用springboot项目&#xff0c;在IDEA 中集成Docker生成镜像&#xff0c;并将镜像发布到linux服务器 具体步骤如下&#xff1a; 1、Centos7安装Docker 更新系统的软件包列表 sudo yum update安装Docker所需的软件包和依赖项&#xff1a; sudo yum install docker完成…

华为OD机试 - 数字序列比大小 - 贪心算法(Java 2023 B卷 100分)

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 一、题目描述 A&#xff0c;B两个人万一个数字比大小的游戏&#xff0c;在游戏前&#xff0c;两个人会拿…

Linux 内核动态打印调试(dev_info、 dev_dbg )

目录 前言 1 printk消息级别 2 调整内核printk打印级别 3 dev_xxx函数简介 4 配置内核使用动态打印 5 动态调试使用方法 6 动态打印调试的基本原理 &#x1f388;个人主页&#x1f388;&#xff1a;linux_嵌入式大师之路的博客-CSDN博客&#x1f389;&#x1f389;&…

xss-labs靶场通关详解

文章目录 前言level1level2level3level4level5level6level7level8level9level10level11level12level13level14level15level16level17level18level19&level20 前言 赶着假期结尾的时候&#xff0c;赶紧给自己找点任务做。现在对xss还是一知半解&#xff0c;只是了解个大概&a…

Java seven 解读正则表达式、java方法的使用

目录 Java 正则表达式1. java.util.regex 包2. 捕获组3. 正则表达式语法4. Matcher 类的方法 Java 方法1. 定义&#xff1a;2. 优点3. 命名规则4. 方法调用5. 方法的重载6. 构造方法7. 可变参数8. finalize() 方法 Java 正则表达式 1. java.util.regex 包 Pattern 类&#xff…