当前位置: 首页 > news >正文

由because it is a JDK dynamic proxy that implements温习Spring的代理

由because it is a JDK dynamic proxy that implements温习Spring的代理

  • 项目场景
  • 原因分析
    • 1、报错位置
    • 2、错误原因
    • 3、业务需求
  • 解决方案
    • 1、注入CGlib代理
    • 2、取出原生对象

项目场景

昨日在启动一个SpringBoot项目时,发现启动失败,并在日志中出现了这样的报错:

The bean ‘XXXXManageImpl‘ could not be injected as a ‘XXXXManageImpl‘ because it is a JDK dynamic proxy that implements : XXXXManage

有些Spring版本则是 The bean ‘XXXXX’ could not be injected because it is a JDK dynamic proxy,如下:

在这里插入图片描述

我们先来看一下产生报错的相关代码

// 类的定义
@Service
public class XXXXManageImpl extends AbstractManage implements XXXXManage {}
// 其他地方要注入 XXXXManageImpl
@Autowired
XXXXManageImpl XXXXManageImpl;

原因分析

1、报错位置

形如

***************************
APPLICATION FAILED TO START
***************************

这种报错实际上是 SpringBoot 分析后的报错,而根据输出的内容看,其原始报错类型其实为 BeanNotOfRequiredTypeException , 经由BeanNotOfRequiredTypeFailureAnalyzer 分析后输出的指导性错误。那么顾名思义,这应该是在Bean装配过程中,出现了指定类型与Bean实际类型不符的场景。

2、错误原因

其实从报错中也不难看出来,说的就是我们希望注入一个类型为”XXXXManageImpl“的Bean,系统确认了这个Bean是存在的,但是现在这个Bean的实例的类型却并不是 ”XXXXManageImpl“,而是一个JDK代理类(com.sum.Proxy),两者虽然都实现了XXXXManager,但只属于兄弟类,此时自然无法注入成功
在这里插入图片描述

如果你还不太清楚动态代理,可以在过去的文章中复习一下《Spring核心特性—— AOP(面向切面编程)》。 一个类如果带有@Component或者@Service等注解,就会被实例化后放进Spring容器。至于最终放进去的可能是这个类的实例,也可能是这个类的代理类的实例
在这里插入图片描述

而至于这个类什么情况下会生成动态代理?其实原因有很多,比如这里我们使用的这个 ”XXXXManageImp“ ,在他的方法中存在着@Transactionol注解,正因为这个注解,导致这个类在创建Bean,并放入Spring容器时,其实放进去的是这个类的代理,而且是JDK代理 (可参见 《Spring事务畅谈 —— 由浅入深彻底弄懂 @Transactional注解》)

而JDK代理的实例类型为 com.sum.Proxy jdk.proxy3.$ProxyXXXX 等(不同jdk版本可能有所不同),但肯定不是我们的业务类 XXXXManageImpl, 所以这次注入是肯定会失败的。

3、业务需求

一般来说,如果我们对一个接口 XXXXManage 有一个实现类 XXXXManageImpl,那么我们在其他地方注入这个Bean 时,最好使用注入的是接口,即如下:

@Autowired
XXXXManage XXXXManage;

但是原代码为什么注入的是实现类呢? 是因为这个实现类本身除了实现了XXXXManage接口外,还继承了一个名叫 AbstractManage 的抽象类,也就是说这个类不单纯是某个接口的实现,他还肩负着一些额外的功能与方法

// 类的定义
@Service
public class XXXXManageImpl extends AbstractManage implements XXXXManage {}

而业务需要调用的就是这个类的其他方法(而非来自接口XXXXManage的方法),所以不能使用注入XXXXManage 的方式。


解决方案

结合我们的业务,我们的核心问题是:我们想要注入一个类,并使用该类自身的方法。但是这个类实际在Spring容器中以JDK代理形式存在,所以如果注入其代理 -> 则无法用到该类自身方法; 注入原生类 -> 启动报错。

所以问题的解决思路可以有以下几种:

1、注入CGlib代理

这也是Spring推荐的一种策略:其原文如下:

Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxiesby setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.
考虑将该 Bean 注入为其接口之一,或者通过在 @EnableAsync 和/或 @EnableCaching 上设置 proxyTargetClass=true 来强制使用基于 CGLib 的代理。

但是我们这里的动态代理,实际是由 @Trasactionol引入的,而@Trasactionol 并没有proxyTargetClass 属性。我们当然可以使用全局的 proxyTargetClass 来解决,比如在配置文件中配置,或者在启动类上的@EnableTransactionManagement注解里加这个属性

@EnableTransactionManagement(proxyTargetClass = true)

而且SpringBoot2就已经将CGlib动态代理设为默认配置,但是由于项目本身是个老项目,积重难返,这个项目一旦全体采用 CGLib 的代理 会导致很多问题。(详见《【问题处理】—— SpringBoot2 动态代理问题排查》)

所以应该说:如果没有历史负债的项目,可以使用这种方式,从而解决该问题。

2、取出原生对象

既然不能使用CGlib,可以采用原生对象解决该问题,即我们虽然是注入代理对象,但在要用到类自己的方法时,可先取出代理的原生对象,然后调用原生对象的方法

// 注入时还是注入JDK代理
@Autowired
XXXXManage XXXXManage;// 需要获取原对象时
XXXXManageImpl obj = (XXXXManageImpl)AopProxyUtils.getSingletonTarget(XXXXManage);

通过AopProxyUtils的方法,就可以通过代理对象,获取其原始对象,进而开始使用了。需要注意的是我们取得并使用原对象,就意味着失去了代理的那些功能。所以这种操作还是需要谨慎一些的

相关文章:

由because it is a JDK dynamic proxy that implements温习Spring的代理

由because it is a JDK dynamic proxy that implements温习Spring的代理 项目场景原因分析1、报错位置2、错误原因3、业务需求 解决方案1、注入CGlib代理2、取出原生对象 项目场景 昨日在启动一个SpringBoot项目时,发现启动失败,并在日志中出现了这样的…...

mac相关命令

显示和隐藏usr等隐藏文件文件 terminal输入: defaults write com.apple.Finder AppleShowAllFiles YESdefaults write com.apple.Finder AppleShowAllFiles NO让.bashrc每次启动shell自动生效 编辑vim ~/.bash_profile 文件, 加上 if [ -f ~/.bashrc ]; then. ~/.bashrc fi注…...

Banana Pi OpenWRT One 官方路由器的第一印象

OpenWRT One是OpenWRT开源社区推出的首款官方开发板,与Banana Pi社区共同设计,由Banana Pi制造和发行。路由器采用蓝色铝合金外壳,质感极佳,视觉效果远超宣传图。整体设计简洁,呈长方形,虽然不是特别时尚&a…...

基于SpringBoot的“高考志愿智能推荐系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“高考志愿智能推荐系统”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统总体结构图 系统首页界面 系统注册页…...

探索Hugging Face:开源AI社区的核心工具与应用实践

引言:AI民主化的先锋 在自然语言处理(NLP)领域,Hugging Face已成为开源社区的代名词。这个成立于2016年的平台,通过提供易用的工具和丰富的预训练模型库,彻底改变了开发者使用和部署AI模型的方式。截至202…...

SVM对偶问题

1、对偶问题数学基础 对偶问题:在线性规划中,每一个线性规划问题(称为原问题)都有一个与之对应的对偶问题。从数学形式上看,如果原问题是求解一个线性目标函数的最大值(或最小值),在满足一系列线性不等式&…...

萃取的实现(三)

探测成员 基于SFINAE&#xff0c;判断一个给定类型T&#xff0c;是否含有名为x的成员。 探测类型成员 判断一个给定类型T&#xff0c;是否含有类型成员size_type&#xff0c;源码如下&#xff1a; #include <type_traits> #include <iostream> #include <vect…...

nodejs版本管理,使用 nvm 删除node版本,要删除 Node.js 的某个版本详细操作

要删除 Node.js 的某个版本并保持 Node Version Manager (nvm) 的管理整洁&#xff0c;可以按以下步骤操作&#xff1a; 步骤 1&#xff1a;查看已安装的 Node.js 版本 nvm ls这会列出你通过 nvm 安装的所有 Node.js 版本。输出类似于&#xff1a; -> v18.17.1v16.20…...

openCV中如何实现滤波

图像滤波用于去除噪声和图像平滑&#xff0c;OpenCV 提供了多种滤波器&#xff1a; 1.1. 均值滤波&#xff1a; import cv2# 读取图像 image cv2.imread("example.jpg")# 均值滤波 blurred_image cv2.blur(image, (5, 5)) # (5, 5) 是滤波核的大小 滤波核大小的…...

vscode通过ssh连接服务器实现免密登录+删除

文章目录 参考&#xff1a; 1、 vscode通过ssh连接服务器实现免密登录删除&#xff08;吐血总结&#xff09;...

智能硬件新时代,EasyRTC开启物联音视频新纪元

在万物互联的时代浪潮中&#xff0c;智能硬件正以前所未有的速度融入我们的生活&#xff0c;从智能家居的便捷控制&#xff0c;到智能穿戴设备的健康监测&#xff0c;再到工业物联网的高效管理&#xff0c;智能硬件的应用场景不断拓展。而在这个智能硬件蓬勃发展的背后&#xf…...

《机器学习数学基础》补充资料:求解线性方程组的克拉默法则

《机器学习数学基础》中并没有将解线性方程组作为重点&#xff0c;只是在第2章2.4.2节做了比较完整的概述。这是因为&#xff0c;如果用程序求解线性方程组&#xff0c;相对于高等数学教材中强调的手工求解&#xff0c;要简单得多了。 本文是关于线性方程组的拓展&#xff0c;供…...

mysql的rpm包安装

(如果之前下载过mariadb&#xff0c;使用yum remove mariadb卸载&#xff0c;因为mariadb与rpm包安装的mysql有很多相似的组件和文件&#xff0c;会发生冲突&#xff0c;而源码包安装的mysql不会&#xff0c;所以不用删除源码包安装myqsl&#xff0c;只删除mariadb就可以&#…...

TailwindCss的vue3安装使用

按照官网的安装教程&#xff0c;属性最后无法生效&#xff0c;这是自我改良版&#xff0c;添加了额外步骤&#xff0c;但是每次引入新的tailwindcss属性 需要重新跑一次项目 npm下载tailwindcss npm install -D tailwindcss npx初始化tailwind配置 npx tailwindcss init 此时根…...

foobar2000设置DSP使用教程及软件推荐

foobar2000安卓中文版&#xff1a;一款高品质手机音频播放器 foobar2000安卓中文版是一款备受好评的高品质手机音频播放器。 几乎支持所有的音频格式&#xff0c;包括 MP3、MP4、AAC、CD 音频等。不论是经典老歌还是最新的流行音乐&#xff0c;foobar2000都能完美播放。除此之…...

开源多商户商城源码最新版_适配微信小程序+H5+APP+PC多端

在数字化时代&#xff0c;电子商务已经成为各行业不可或缺的一部分&#xff0c;开源多商户商城源码为中小企业和个人开发者提供了快速搭建和定制电商平台的利器。分享一款最新版的开源多商户商城源码&#xff0c;它能够适配微信小程序、H5、APP和PC等多个端口&#xff0c;满足商…...

【matlab】大小键盘对应的Kbname

matlab中可以通过Kbname来识别键盘上的键。在写范式的时候&#xff0c;遇到一个问题&#xff0c;我想用大键盘上排成一行的数字按键评分&#xff0c;比如 Kbname(1) 表示键盘上的数字1&#xff0c;但是这种写法只能识别小键盘上的数字&#xff0c;无法达到我的目的&#xff0c;…...

go语言并发的最佳实践

Go 语言的并发模型是其最强大的特性之一&#xff0c;基于 CSP&#xff08;Communicating Sequential Processes&#xff09;理论&#xff0c;通过 goroutine 和 channel 实现轻量级并发. 一、并发核心概念 1. Goroutine 在 Go 语言中&#xff0c;Goroutine 是实现并发编程的…...

超全Deepseek资料包,deepseek下载安装部署提示词及本地部署指南介绍

该资料包涵盖了DeepSeek模型的下载、安装、部署以及本地运行的详细指南&#xff0c;适合希望在本地环境中高效运行DeepSeek模型的用户。资料包不仅包括基础的安装步骤&#xff0c;还提供了68G多套独立部署视频教程教程&#xff0c;针对不同硬件配置的模型选择建议&#xff0c;以…...

重看Spring聚焦BeanDefinition分析和构造

目录 一、对BeanDefinition的理解 &#xff08;一&#xff09;理解元信息 &#xff08;二&#xff09;BeanDefinition理解分析 二、BeanDefinition的结构设计分析 &#xff08;一&#xff09;整体结构体会 &#xff08;二&#xff09;重要接口和类分析 三、构造 BeanDef…...

从MySQL5.7平滑升级到MySQL8.0的最佳实践分享

一、前言 升级需求&#xff1a;将5.7.35升级到8.0.27, 升级方式 in-place升级【关闭现有版本MySQL&#xff0c;将二进制或包替换成新版本并在现有数据目录上启动MySQL并执行升级任务的方式&#xff0c;称为in-place升级】 原版本 5.7.35 CentOS Linux release 7.9.2009 新版本…...

Node-Red

是什么? ——基于浏览器的流程编辑工具可连接设备、服务器和API应用 一、安装 1、本地安装(Windows) 在电脑上安装 Node.js 环境,然后使用 NPM 安装 Node-RED Node.js介绍: JavaScript 在不同的位置有不一样的解析器 写入 HTML 的 JS 语言,浏览器即它的解析器需要独…...

GO语言的安装以及第一个Go语言程序

1. Go语言的安装与设置 官网:golang.org 国内下载:https://studygolang.com/dl 国内镜像:https://goproxy.cn/ 2. GOland的安装 Go 1.13 及以上&#xff08;推荐&#xff09; 打开你的终端并执行 $ go env -w GO111MODULEon $ go env -w GOPROXYhttps://goproxy.cn,direc…...

年前集训总结python

1.用空格隔开输出列表list1 print(" ".jion(map(str,list1))) 2.转换函数 int() 将一个数字或字符串转换为整数。可以指定基数&#xff0c;支持从其他进制&#xff08;如二进制、十六进制&#xff09;转换为十进制。 int(101, 2) # 二进制字符串转十进制 > 5 …...

【JAVA实战】JAVA实现Excel模板下载并填充模板下拉选项数据

背景 有这样一个场景&#xff1a;前端下载Excel模板&#xff0c;进行数据导入&#xff0c;这个下载模板过程需要经过后端接口去数据库查询数据进行某些列的下拉数据填充&#xff0c;下拉填充的数据过程中会出现错误String literals in formulas can’t be bigger than 255 cha…...

【linux】在 Linux 上部署 DeepSeek-r1:32/70b:解决下载中断问题

【linux】在 Linux 上部署 DeepSeek-r1:32/70b:解决下载中断问题 【承接商业广告,如需商业合作请+v17740568442】 文章目录 【linux】在 Linux 上部署 DeepSeek-r1:32/70b:解决下载中断问题问题描述:解决方法方法一:手动中断并重启下载方法二:使用 Bash 脚本自动化下载在…...

Rust 面试题

1. Rust 中的所有权(Ownership)是什么? 回答: 所有权是 Rust 的核心概念之一,每个值在 Rust 中都有一个唯一的所有者,并且所有权在作用域内转移。当所有者离开作用域时,Rust 会自动释放该值的内存,避免了内存泄漏。 代码示例: fn main() {let s1 = String::from(&q…...

Copilot Next Edit Suggestions(预览版)

作者&#xff1a;Brigit Murtaugh&#xff0c;Burke Holland 排版&#xff1a;Alan Wang 我们很高兴向你介绍在本次 Visual Studio Code 发布中&#xff0c;关于 GitHub Copilot 的三个预览功能&#xff1a; Next Edit Suggestions&#xff08;NES&#xff09;Copilot Edits 的…...

LeetCode - 18 四数之和

题目来源 18. 四数之和 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一…...

汽车零部件开发应该具备哪些编程思维?

目录 1、功能安全思维 2、实时性与确定性思维 3、可靠性和冗余思维 4、硬件软件协同思维 5、CAN总线通信思维 6、故障诊断和自诊断思维 7、功耗优化思维 8、软件更新和版本管理思维 9、用户体验与安全性思维 汽车零部件开发中&#xff0c;嵌入式软件在车辆系统中的作用…...

在Windows系统中安装Open WebUI并连接Ollama

Open WebUI是一个开源的大语言模型&#xff08;LLM&#xff09;交互界面&#xff0c;支持本地部署与离线运行。通过它&#xff0c;用户可以在类似ChatGPT的网页界面中&#xff0c;直接操作本地运行的Ollama等大语言模型工具。 安装前的核心要求&#xff1a; Python 3.11&#…...

React 与 Vue 对比指南 - 上

React 与 Vue 对比指南 - 上 本文将展示如何在 React 和 Vue 中实现常见功能&#xff0c;从基础渲染到高级状态管理 Hello 分别使用 react 和 vue 写一个 Hello World&#xff01; react export default () > {return <div>Hello World!</div>; }vue <…...

自动化办公|通过xlwings进行excel格式设置

1. 介绍 xlwings 是一个强大的 Python 库&#xff0c;可以用来操作 Excel&#xff0c;包括设置单元格格式、调整行高列宽、应用条件格式以及使用内置样式。本文将详细介绍如何使用 xlwings 进行 Excel 格式化操作&#xff0c;并附带代码示例。 2. 基础格式设置&#xff08;字…...

c# -01新属性-模式匹配、弃元、析构元组和其他类型

文章目录 **学习摘抄分享**模式匹配概述Null 检查类型测试比较离散值关系模型多个输入ObServation列表模式弃元元组和对象析构利用switch的模式进行匹配对于out的方法调用独立弃元析构元组和其他类型元组方法一方法二方法三方法四使用弃元元组的元素使用弃元的用户定义类型解构…...

银河麒麟V10SP1下qt5-12-12编译环境配置

下面的脚本在兆芯版kylin上试过,如果是本地编译,arm版应该也没有问题 a. 如果执行脚本安装有问题&#xff0c;读者可以拷贝命令多次安装 b. 建议在虚拟机环境下进行 #!/bin/bashsudo apt updatesudo apt-get install g gcc make cmake gperf bison flex libdrm-dev libxcompos…...

轻松搭建本地大语言模型(一)Ollama安装与使用

Ollama 是一款开源的本地大语言模型运行框架&#xff0c;支持在 Windows、macOS 和 Linux 系统上运行&#xff0c;能够帮助用户轻松下载和使用各种大语言模型&#xff08;例如deepseek、llama、qwen&#xff09;。本文将详细介绍 Ollama 的安装步骤&#xff0c;帮助你快速搭建本…...

【深度学习】Transformer入门:通俗易懂的介绍

【深度学习】Transformer入门&#xff1a;通俗易懂的介绍 一、引言二、从前的“读句子”方式三、Transformer的“超级阅读能力”四、Transformer是怎么做到的&#xff1f;五、Transformer的“多视角”能力六、Transformer的“位置记忆”七、Transformer的“翻译流程”八、Trans…...

浅识Linux高阶用法

&#xff08;前记&#xff1a;内容有点多&#xff0c;先看目录再挑着看。&#xff09; 问题&#xff1a;在Java面试中&#xff0c;当被提问到Linux的高阶用法以及如何使用Linux将程序、数据库、中间件等部署在云上时&#xff0c;可以从以下几个方面进行回答&#xff1a; Li…...

I²C简介

前言 IC&#xff08;Inter-Integrated Circuit, 内置集成电路&#xff09;总线是由Philips公司&#xff08;现属于恩智浦&#xff09;在上世纪80年代开发的两线式串行通信总线&#xff0c;用于连接微控制器及其外围设备&#xff0c;控制设备之间的通信。 IC总线的物理拓扑示意…...

Linux定时静默执行桌面/前台程序

Linux服务器上的程序大都在后台默默的执行&#xff0c;但有些需要在前台或桌面上运行的程序该怎么办呢&#xff1f;这就要借助虚拟显示技术&#xff0c;也就是在后台运行时提供虚拟的显示&#xff0c;使前台运行的程序也能默默的在后台运行&#xff0c;这就是所谓的以“无头模式…...

Redux中间件redux-thunk和redux-saga的具体区别是什么?

Redux 中间件是增强 Redux 功能的重要工具&#xff0c;redux-thunk 和 redux-saga 是两个常用的中间件&#xff0c;它们在处理异步操作和副作用时提供了不同的方式和理念。以下是两者的具体区别&#xff1a; 1. 概念与设计理念 redux-thunk 简洁&#xff1a;redux-thunk 是一…...

【STM32】DRV8833驱动电机

1.电机如何转动 只需要给电机两个端子加一正一负的极性就会转起来了&#xff0c;但是要注意的是不要将电机两端直接接在5v和gnd之间&#xff0c;这种电机一般要提供几百毫安的电流&#xff0c;而GPIO口只能提供几毫安&#xff0c;所以我们使用一个DRV8833来驱动 DRV8833输入口…...

【go语言规范】 使用函数式选项 Functional Options 模式处理可选配置

如何处理可选配置&#xff1f; Config Struct 方式 (config-struct/main.go) 这是最简单的方式&#xff0c;使用一个配置结构体&#xff1a; 定义了一个简单的 Config 结构体&#xff0c;包含 Port 字段创建服务器时直接传入配置对象优点&#xff1a;简单直接缺点&#xff1a…...

vue中为组建添加样式的方式

在 Vue 中&#xff0c;可以通过多种方式为 view 添加样式&#xff0c;并且支持动态绑定样式。以下是几种常见的方式&#xff1a; 1. 内联样式 直接在模板中使用 style 属性来添加样式。 <template><div style"color: red; font-size: 14px;">这是一个…...

如何简单的去使用jconsloe 查看线程 (多线程编程篇1)

目录 前言 1.进程和线程 进程 PCB 的作用 并发编程和并行编程 线程 为什么选择多线程编程 2.在IDEA中如何简单创建一个线程 1. 通过继承Thread类 2. 通过实现 Runnable 接口 3. 使用 Lambda 表达式 3.如何简单使用jconsloe去查看创建好的线程 前言 2025来了,这是第…...

机器学习·最近邻方法(k-NN)

前言 上一篇简单介绍了决策树&#xff0c;而本篇讲解与决策树相近的 最近邻方法k-NN。 机器学习决策树-CSDN博客 一、算法原理对比 特性决策树最近邻方法&#xff08;k-NN&#xff09;核心思想通过特征分割构建树结构&#xff0c;递归划分数据基于距离度量&#xff0c;用最近…...

网络安全试题

ciw网络安全试题 &#xff08;1&#xff09;&#xff08;单选题&#xff09;使网络服务器中充斥着大量要求回复的信息&#xff0c;消耗带宽&#xff0c;导致网络或系统停止正常服务&#xff0c;这属于什么攻击类型? A、拒绝服务 B、文件共享 C、BIND漏洞 D、远程过程调用 &a…...

沃丰科技大模型标杆案例 | 索尼大模型智能营销机器人建设实践

AI大模型发展日新月异&#xff0c;国内外主流大模型每月必会升级。海外AI大模型市场由美国主导&#xff0c; 各模型已形成“多强竞合”的局面。中国积极响应全球大模型技术的发展趋势&#xff0c;高校、研究院所等科研机构、互联网企业&#xff0c;人工智能企业均不同程度地投入…...

​ ​rust学习四、控制语句

rust的控制语句和大部分语言没有什么区别&#xff0c;都是熟悉的for,while,loop,if。 比较不同的是&#xff0c;在绝大部分非常流行的语言中都有的switch&#xff0c;rust是没有的。 诸如c/c,java,javascript,c#。连PL/SQL都有case when语句。 一、基本的for、while、if&…...

会员购交易系统架构演进

本期作者 1.背景 会员购是B站2017年推出的IP消费体验服务平台&#xff0c;在售商品以手办、漫画、JK制服等贴合平台生态的商品为主。随着业务发展&#xff0c;会员购从最开始的预售&#xff0c;现货拓展到全款预售&#xff0c;盲盒&#xff0c;众筹等多种售卖方式&#xff0c;销…...