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

spring boot 2升级为spring boot 3中数据库连接池druid的问题

目录

ConfigurationClassPostProcessor

ConfigurationClassBeanDefinitionReader

MybatisPlusAutoConfiguration

ConditionEvaluator

OnBeanCondition

总结


近期给了一个任务,要求是对现有的 spring boot 2.x 项目进行升级,由于 spring boot 2.x 版本已经结束技术支持,所以需要升级为 spring boot 3.x

https://spring.io/blog/2023/11/23/spring-boot-2-7-18-available-now/

 

升级后报了一个 mybatis 的问题,如下

Caused by: java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are requiredat org.springframework.util.Assert.notNull(Assert.java:172)at org.mybatis.spring.support.SqlSessionDaoSupport.checkDaoConfig(SqlSessionDaoSupport.java:125)at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:73)at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1822)at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1771)... 49 common frames omitted

即 SqlSessionFactory 没获取到,这个是操作 mybatis 必须要用的对象,这个竟然没有。

目前项目中使用的 mybatis 是增强版的 mybatis-plus,即在启动的时候启动 spring ioc 容器的时候没有找到 sqlSessionFactory 对象,鉴于是升级到新版本,考虑到版本变动大,所以自己新建了一个 spring boot 3 项目,来验证一下新的是否可以正常执行。

spring boot 3 项目中的 pom.xml 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.0</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>mybatis-plus-spring-boot-3</artifactId><version>0.0.1-SNAPSHOT</version><name>mybatis-plus-spring-boot-3</name><description>Demo project for Spring Boot</description><properties><java.version>21</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.5</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

启动之后,发现正常。

那就是 mybatis-plus 哪里有问题了,跟进通过 AbstractApplicationContext#refresh() 跟进,发现在 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry() 调用 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 时出现了问题。

ConfigurationClassPostProcessor

ConfigurationClassBeanDefinitionReader

主要在 ConfigurationClassBeanDefinitionReader#loadBeanDefinitions() 中

其中,正常的 shouldSkip() 的返回值是 false,即执行接下来的 MybatisPlusAutoConfiguration$MapperScannerRegistrarNotFoundConfiguration 中的逻辑,将 MapperScannerConfigurer 类注册到 spring ioc 容器中。

MybatisPlusAutoConfiguration

看看 shouldSkip() 的 true 值是怎么来的

ConditionEvaluator

查看是如下的判断

这里有两个类,分别是 OnBeanCondition 和 OnClassCondition,其中 OnClassCondition 执行无异常,问题主要在 OnBeanCondition 上。

接下来对比一下看看两者变量赋值的区别

新项目没问题的

OnClassConditionrequiredPhase == null
truerequiredPhase == phase
false(requiredPhase == null || requiredPhase == phase)
truecondition.matches(this.context, metadata)
true!condition.matches(this.context, metadata)
false(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
falseOnBeanConditionrequiredPhase == null
falserequiredPhase == phase
true(requiredPhase == null || requiredPhase == phase)
truecondition.matches(this.context, metadata)
true!condition.matches(this.context, metadata)
false(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
false

原项目有问题的

OnClassConditionrequiredPhase == null
truerequiredPhase == phase
false(requiredPhase == null || requiredPhase == phase)
truecondition.matches(this.context, metadata)
true!condition.matches(this.context, metadata)
false(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
falseOnBeanConditionrequiredPhase == null
falserequiredPhase == phase
true(requiredPhase == null || requiredPhase == phase)
truecondition.matches(this.context, metadata)
false!condition.matches(this.context, metadata)
true(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
true

可以看到是 OnBeanCondition#matches() 返回有问题。

那就调试进去看一下

OnBeanCondition

发现在升级项目中变量 unmatchedTypes 中多了一个 javax.sql.DataSource 导致了返回结果为 false,进而导致了接下来的问题。

其中,isAllMatched() 的判断逻辑为 unmatchedAnnotations、unmatchedNames、unmatchedTypes 必须为空。

这就让我 想到了数据源的问题,项目中使用了阿里巴巴开源的连接池 druid,是不是没注册进这个对象?后面发现了引入的依赖中没有针对 spring boot 3 的自动装配进行处理。

在项目的 src/main/resources 下创建文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

内容如下

com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure

启动正常。

后面又去 github 上看了一下

https://github.com/alibaba/druid

发现对于 spring boot 3 做了适配

https://github.com/alibaba/druid/releases/tag/1.2.20

可以看到,在 2023.10.08 日处理了这个问题。

看 maven 仓库,引入 1.20.0 及以上的版本即可。

<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.21</version>
</dependency>

通过源码对比,发现 druid-spring-boot-starter 不兼容 druid-spring-boot-3-starter,druid-spring-boot-3-starter 是专门对 spring boot 3 进行了适配。

对比源码发现,1.2.18 和 1.2.19 对于 spring boot 3 适配都有问题。

总结

针对项目中的问题很多,尤其是 spring boot 3 带来的变化大,针对一些问题,需要从源码层次入手看问题。

之前整理的升级相关的文章

https://blog.csdn.net/zlpzlpzyd/article/details/134203560

https://blog.csdn.net/zlpzlpzyd/article/details/133160643

https://blog.csdn.net/zlpzlpzyd/article/details/132779246

参考链接

https://blog.csdn.net/weixin_43333483/article/details/131355109

https://www.cnblogs.com/jimmyhu/p/17300314.html

https://juejin.cn/post/7165884190028726308

相关文章:

spring boot 2升级为spring boot 3中数据库连接池druid的问题

目录 ConfigurationClassPostProcessor ConfigurationClassBeanDefinitionReader MybatisPlusAutoConfiguration ConditionEvaluator OnBeanCondition 总结 近期给了一个任务&#xff0c;要求是对现有的 spring boot 2.x 项目进行升级&#xff0c;由于 spring boot 2.x 版…...

客服系统配置之Nginx处理静态资源和动态请求

Nginx直接处理静态资源&#xff0c;接口动态请求走反向代理到后端 这样可以减轻后端服务的压力 location / {try_files $uri kefu; }location kefu {# 这里是命名位置 kefu 的配置proxy_pass http://backend-server;# 其他反向代理的配置... }如果请求的是静态资源&#xff08…...

Golang 切片

前言 在Go语言中&#xff0c;切片是一个引用类型&#xff0c;它提供了对数组的动态窗口。切片并不存储任何数据&#xff0c;它只是描述了底层数组中的一个片段。切片的定义包括三个部分&#xff1a;指向数组的指针、切片的长度和切片的容量 基本使用 声明切片&#xff1a;声…...

防止公司办公终端文件数据 | 资料外泄,——自动智能透明加密防泄密软件系统

天锐绿盾公司电脑文件数据资料透明加密防泄密软件系统是一款专门用于保护企业电脑文件数据安全的软件系统。它采用透明加密技术&#xff0c;能够在不影响员工正常工作的情况下&#xff0c;对电脑上的文件数据进行自动加密&#xff0c;从而有效防止企业数据泄密。 PC端访问地址&…...

C#-枚举

枚举类型 (enum type) 是具有一组命名常量的独特的值类型。 下面的示例声明并使用一个名为 Color 的枚举类型&#xff0c;该枚举具有三个常量值 Red、Green 和 Blue&#xff1a; using System; using System;enum Color {Red,Green,Blue }class Test {static void PrintColor(…...

Java后端开发——SSM整合实验

文章目录 Java后端开发——SSM整合实验一、常用方式整合SSM框架二、纯注解方式整合SSM框架 Java后端开发——SSM整合实验 一、常用方式整合SSM框架 1.搭建数据库环境&#xff1a;MySQL数据库中创建一个名称为ssm的数据库&#xff0c;在该数据库中创建一个名称为tb_book的表 …...

VMware虚拟机安装Ubuntu

准备:Ubuntu的镜像文件,VMware,手. 1.新建虚拟机&#xff0c;选择自定义&#xff0c;下一步。 2.硬件兼容性&#xff0c;选择Workstation 16.x&#xff0c;下一步。 3.选择安装程序光盘映像文件&#xff0c;路径为映像文件所在文件夹&#xff0c;下一步。 4. 创建用户和设置密…...

用一个简单的例子说明单细胞分析中的dgCMatrix数据的结构

dgCMatrix用来存储矩阵的一种数据格式&#xff0c;这种数据格式很适合存储稀疏矩阵&#xff08;即矩阵中大部分值为0&#xff09;。dgCMatrix使用三个数组&#xff08;分别是i&#xff0c;p&#xff0c;x&#xff09;来存储矩阵。怎么存的呢&#xff1f; 先举一个普通矩阵的例…...

【小工具】pixi-live2d-display,直接可用的live2d的交互网页/桌面应用

效果&#xff1a; <script src"https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js"></script> <script src"https://cdn.jsdelivr.net/gh/dylanNew/live2d/webgl/Live2D/lib/live2d.min.js"></script> <…...

vulhub中的Nginx漏洞的详细解析

Nginx漏洞 1.cd到nginx_parsing_vulnerability cd /opt/vulhub/nginx/nginx_parsing_vulnerability 2.执行docker-compose up -d 3.查看靶场是否开启成功 dooker ps 4.访问浏览器 因为这里是80端口所以直接使用ip就能访问成功 5.上传图片 注意这里的图片是含有一句话木马的图…...

如何实现公网访问GeoServe Web管理界面共享空间地理信息【内网穿透】

文章目录 前言1.安装GeoServer2. windows 安装 cpolar3. 创建公网访问地址4. 公网访问Geo Servcer服务5. 固定公网HTTP地址 前言 GeoServer是OGC Web服务器规范的J2EE实现&#xff0c;利用GeoServer可以方便地发布地图数据&#xff0c;允许用户对要素数据进行更新、删除、插入…...

k8s-存储 11

一、configmapu存储 首先&#xff0c;确保集群正常&#xff0c;节点都处于就绪状态 Configmap用于保存配置数据&#xff0c;以键值对形式存储。configMap资源提供了向 Pod 注入配置数据的方法&#xff0c;旨在让镜像和配置文件解耦&#xff0c;以便实现镜像的可移植性和可复用…...

蓝牙信标定位原理

定位原理&#xff1a;蓝牙信标的定位原理是基于RSSI蓝牙信号强度来做定位的。 根据应用场景不同&#xff0c;通过RSSI定位原理可分为两种定位方式 一、存在性定位 这种方式通常要求所需定位的区域安装一个蓝牙信标即可&#xff0c;手持终端扫描蓝牙信标信号&#xff0c;扫描…...

单片机期末复习

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、单片机…...

springboot虹软人脸识别集成

准备工作 虹软开放平台中创建一个新的应用 虹软开发平台【点我跳转】 开始上代码 基本配置 将下载的jar包放到src同级目录下 <!-- 虹软--><dependency><groupId>com.arcsoft.face</groupId><artifactId>arcsoft-sdk-face</artifactI…...

Element+vue3.0 tabel合并单元格span-method

Elementvue3.0 tabel合并单元格 span-method :span-method"objectSpanMethod"详解&#xff1a; 在 objectSpanMethod 方法中&#xff0c;rowspan 和 colspan 的值通常用来定义单元格的行跨度和列跨度。 一般来说&#xff0c;rowspan 和 colspan 的值应该是大于等于…...

Python学习笔记第七十九天(OpenCV轨迹栏)

Python学习笔记第七十九天 OpenCV轨迹栏cv.createTrackbarcv.getTrackbarPos两者合并运用 后记 OpenCV轨迹栏 cv.getTrackbarPos 和 cv.createTrackbar 是 OpenCV 库中用于创建和获取跟踪条位置的函数。这些函数通常用于在视频处理或图像处理应用程序中创建用户界面&#xff0…...

uniapp自定义顶部导航并解决打包成apk后getMenuButtonBoundingClientRect方法失效问题

需求&#xff1a;要在app上的顶部导航提示哪里添加一些东西进去&#xff0c;用uniapp自带的肯定不行啊&#xff0c;所以自定义了所有的页面的顶部导航&#xff0c;之后自定义后用手机调试发现 uni.getMenuButtonBoundingClientRect()这个方法的top获取不到....网上找了很多种方…...

C++入门【26-C++ Null 指针】

在变量声明的时候&#xff0c;如果没有确切的地址可以赋值&#xff0c;为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。 NULL 指针是一个定义在标准库中的值为零的常量。请看下面的程序&#xff1a; 实例 #include <iostream> using…...

Linux第14步_安装FTP服务器

安装“vim编辑器”后&#xff0c;我们紧接着“安装FTP服务器”。 1、在安装前&#xff0c;要检查虚拟机可以上网&#xff0c;否则可能会导致安装失败。 2、在虚拟机界面右击鼠标&#xff0c;弹出下面的对话框 3、点击“打开终端(E)”&#xff0c;得到下面的界面 &#xff1a;…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...