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

news2025/1/12 1:08:42

目录

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 required
	at 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 上。

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

新项目没问题的

OnClassCondition

requiredPhase == null
true

requiredPhase == phase
false

(requiredPhase == null || requiredPhase == phase)
true

condition.matches(this.context, metadata)
true

!condition.matches(this.context, metadata)
false

(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
false

OnBeanCondition

requiredPhase == null
false

requiredPhase == phase
true

(requiredPhase == null || requiredPhase == phase)
true

condition.matches(this.context, metadata)
true

!condition.matches(this.context, metadata)
false

(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
false

原项目有问题的

OnClassCondition

requiredPhase == null
true

requiredPhase == phase
false

(requiredPhase == null || requiredPhase == phase)
true

condition.matches(this.context, metadata)
true

!condition.matches(this.context, metadata)
false

(requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)
false

OnBeanCondition

requiredPhase == null
false

requiredPhase == phase
true

(requiredPhase == null || requiredPhase == phase)
true

condition.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

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

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

相关文章

计算机环境安全

操作系统安全----比如windows,linux 安全标识--实体唯一性 windows---主体&#xff1a;账户&#xff0c;计算机&#xff0c;服务 安全标识符SID-Security Identifier 普通用户SID是1000&#xff0c;管理用SID是500 linux---主体&#xff1a;用户&#xff0c;用户组&#xf…

华为面经总结

为了帮助大家更好的应对面试&#xff0c;我整理了往年华为校招面试的题目&#xff0c;供大家参考~ 面经1 技术一面 自我介绍说下项目中的难点volatile和synchronized的区别&#xff0c; 问的比较细大顶堆小顶堆怎么删除根节点CSRF攻击是什么&#xff0c;怎么预防线程通信方式…

C++ STL set用法详解

目录 1.set的创建。 具体例子&#xff1a; set初始化&#xff1a; 2.set的特性。 3.set元素遍历&#xff1a; 迭代器创建&#xff1a; 4.set的基本函数。 4.1.insert() 4.2 clear() 4.3 find() 4.4 erase() 4.5 count() 4.6 size() 4.7 empty 4.8 lower_boun…

NGUI基础-三大基础组件之Event System(Uicameras)

目录 主要作用 相关参数 (建议&#xff1a;红色是重点&#xff0c;黑色的了解即可&#xff09; Event Type Events go to Process Events in Event Mask​编辑 Debug Command Click Allow Multi Touch Auto Hide Cursor Sticky ToolTip/Long press ToolTip/ToolTip…

【漏洞挖掘】挖掘CNVD证书

文章目录 一、CNVD介绍事件型漏洞通用型漏洞 二、挖掘思路1. 黑盒测试资产搜集fofa API筛选脚本 2. 白盒测试代码审计 3. google hack注意事项 一、CNVD介绍 国家信息安全漏洞共享平台&#xff08;简称CNVD&#xff09;&#xff0c;对于白帽子来说&#xff0c;挖掘的漏洞提交后…

【Docker】创建,查看,进入容器

目录 方式一&#xff1a; 创建 查看 ​编辑 方式二&#xff1a; 创建 查看 进入容器 方式一&#xff1a; 首先查看有什么镜像 创建 docker run -i -t --namefreedom centos:7 /bin - i 表示容器一直运行着&#xff0c;容器如果没有客户端连接就会关闭&#xff0c;加了…

python中抓取小米应用商城xpath实例

页面源码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <title>手机游戏应用商店_软件商店app下载-小米应用商店</title> <…

nvidia-smi 完整查看显卡型号

当我们在使用nvidia-smi查看显卡的型号的时候&#xff0c;会发现出现如下问题&#xff1a; 可以看到我们此时无法看到显卡的准确型号&#xff0c;只能看到NVIDIA GeForce ... 解决方法&#xff1a;使用如下命令即可完整显示显卡型号 nvidia-smi -L 如下所示&#xff1a;

嵌入式代码经常产生bug的五大原因

在嵌入式开发软件中查找和消除潜在的错误是一项艰巨的任务。 通常需要英勇的努力和昂贵的工具才能从观察到的崩溃&#xff0c;死机或其他计划外的运行时行为追溯到根本原因。 在最坏的情况下&#xff0c;根本原因会破坏代码或数据&#xff0c;使系统看起来仍然可以正常工作或…

Transformer模型中前置Norm与后置Norm的区别

主要介绍原始Transformer和Vision Transformer中的Norm层不同位置的区别。 文章目录 前言 不同位置的作用 总结 前言 在讨论Transformer模型和Vision Transformer (ViT)模型中归一化层位置的不同&#xff0c;我们首先需要理解归一化层&#xff08;Normalization&#xff09;在…

java数据结构与算法刷题-----LeetCode63. 不同路径 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 很多人觉得动态规划很难&#xff0c;但它就是固定套路而已。其实动态规划只…

Java HashMap 面试题(一)

HashMap 面试题&#xff08;一&#xff09; 文章目录 HashMap 面试题&#xff08;一&#xff09;3.3 面试题-说一下HashMap的实现原理&#xff1f;面试题-HashMap的put方法的具体流程hashMap常见属性源码分析 3.3 面试题-说一下HashMap的实现原理&#xff1f; HashMap的数据结…

Vue3-39-路由-导航异常的检测 afterEatch 与 编程式导航之后的订阅动作

说明 本文主要是介绍一下 路由的后置守卫 afterEatch 的一个重要的作用 &#xff1a; 就是检测路由异常信息。 它的实现方式是 通过第三个参数来返回的。 而且&#xff0c;它的异常检测是全局的。导航的异常有以下三种类型&#xff1a; aborted : 在导航守卫中 被拦截并返回了…

深入Pandas(二):高级数据处理技巧

文章目录 系列文章目录引言时间序列分析可视化示例 高级数据分析技术分组与聚合操作时间序列分析 高级数据操作数据合并与重塑示例&#xff1a;数据合并merge示例&#xff1a;数据合并concat示例&#xff1a;数据重塑 - 透视表 高级索引技巧 结论 系列文章目录 Python数据分析…

B059-权限管理系统01

目录 知识点介绍项目演示项目搭建动态菜单查询分析(权限表分析)权限系统表分析角色模块pageInfopageHelper实现前端动态分页高级查询新增与修改删除角色 分配权限-表分析角色授权数据-一级和二级权限查询 知识点介绍 项目演示 准备数据库 准备工程auth_new tips&#xff1a;…

Java中请求生成唯一追溯TraceId

Java中请求生成唯一追溯TraceId 一&#xff1a;背景 因为是微服务架构,平常日志太多,看日志不太好查,所以想要从一整个链路当中获取一个唯一标识,比较好定位问题&#xff0c; 原理就是从gateway网关将标识传递到下游,下游服务拿到这个标识,响应结束后将traceId反向写入响应体…

Python中的有序字典是什么

有序字典 一、简介 Python中的字典的特性&#xff1a;无序性。 有序字典和通常字典类似&#xff0c;只是它可以记录元素插入其中的顺序&#xff0c;而一般字典是会以任意的顺序迭代的。 二、普通字典 #! /usr/bin/env python3 # -*- coding:utf-8 -*- d1 {} d1[a] A d1[b…

十种编程语言的对比分析

在当今的软件开发领域&#xff0c;编程语言扮演着至关重要的角色。不同的编程语言各有其特点和适用场景&#xff0c;选择合适的编程语言能够提高开发效率和软件质量。本文将对十种常见的编程语言进行对比分析&#xff0c;帮助读者了解它们的优缺点和适用场景。 一、Python Pyt…

微服务实战系列之API加密

前言 随着一阵阵凛冽寒风的呼啸&#xff0c;新的年轮不知不觉滚滚而来。故事随着2023的远去&#xff0c;尘封于案底&#xff1b;希望迎着新年&#xff0c;绽放于枝头。在2024新岁启航&#xff0c;扬帆破浪之时&#xff0c;让烦恼抛洒于九霄&#xff0c;让生机蓬勃于朝朝暮暮。 …

Java 将Excel转换为TXT文本格式

TXT文件是一种非常简单、通用且易于处理的文本格式。在处理大规模数据时&#xff0c;将Excel转为TXT纯文本文件可以提高处理效率。此外&#xff0c;许多编程语言和数据处理工具都有内置的函数和库来读取和处理TXT文件&#xff0c;因此将Excel文件转换为TXT还可以简化数据导入过…