首页 > 编程语言 >SpringBoot源码实用场景:SpringBoot 3.1.0 环境下 PageHelper 1.4.0不生效问题排查

SpringBoot源码实用场景:SpringBoot 3.1.0 环境下 PageHelper 1.4.0不生效问题排查

时间:2023-08-09 16:34:31浏览次数:41  
标签:1.4 SpringBoot pagehelper 源码 PageHelperAutoConfiguration class

1、技术栈:

  JDK 17 + SpringBoot 3.1.0 + PageHelper 1.4.0

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project ...>
 3     <parent>
 4         <groupId>org.springframework.boot</groupId>
 5         <artifactId>spring-boot-starter-parent</artifactId>
 6         <version>3.1.0</version>
 7         <relativePath/>
 8     </parent>
 9     ...
10     <properties>
11         <java.version>17</java.version>
12         <pagehelper.boot.version>1.4.0</pagehelper.boot.version>
13         ...
14     </properties>
15 
16     <dependencyManagement>
17         <dependencies>
18             <!-- pagehelper 分页插件 -->
19             <dependency>
20                 <groupId>com.github.pagehelper</groupId>
21                 <artifactId>pagehelper-spring-boot-starter</artifactId>
22                 <version>${pagehelper.boot.version}</version>
23             </dependency>
24         </dependencies>
25         ...
26     </dependencyManagement>
27 </project>
View Code

 

2、异常表现:

  PageHelper 分页拦截器不生效

3、解决方案:

  将 pagehelper-spring-boot-starter 版本由 1.4.0 升级到 1.4.7 (写这篇博客时的最新版)

4、源码分析:

  分析、解决这个bug需要对PageHelper源码、SpringBoot源码有一定的了解。

  Step1: 首先分页插件PageHelper的本质是mybatis拦截器实现,可以大胆推测其核心类是一个Intercepter, 即 PageIntercepter.class 

1 public class PageInterceptor implements org.apache.ibatis.plugin.Interceptor {
2 ...
3 }
View Code

  Step2: 在 PageIntercepter 核心方法 intercept() 上打断点,debug发现代码运行时没有经过此处断点,推测可能是该 PageIntercepter 没有被创建,或者创建出的对象没有被绑定到 SqlSessionFactory

1     @Override
2     public Object intercept(Invocation invocation) throws Throwable {}
View Code

  Step3: 使用Idea分析 PageIntercepter 的构造方法,发现 PageIntercepter 的构造方法在 PageHelperAutoConfiguration 类的 afterPropertiesSet()  方法中被调用,在 PageHelperAutoConfiguration.afterPropertiesSet() 方法上打断点发现运行时逻辑也没有执行到当前断点

 1 @Configuration
 2 @ConditionalOnBean(SqlSessionFactory.class)
 3 @EnableConfigurationProperties({PageHelperProperties.class, PageHelperStandardProperties.class})
 4 @AutoConfigureAfter(MybatisAutoConfiguration.class)
 5 //@Import(PageHelperProperties.class)
 6 @Lazy(false)
 7 public class PageHelperAutoConfiguration implements InitializingBean {
 8     // ...
 9     @Override
10     public void afterPropertiesSet() throws Exception {
11         PageInterceptor interceptor = new PageInterceptor();
12         interceptor.setProperties(this.properties);
13         for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
14             org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
15             if (!containsInterceptor(configuration, interceptor)) {
16                 configuration.addInterceptor(interceptor);
17             }
18         }
19     }
20 }
View Code

  Step4: 继续分析 PageHelperAutoConfiguration 源码,发现其被 @Configuration 注解标识,且在 com.github.pagehelper.autoconfigure 包下,由此判断 PageHelperAutoConfiguration 是一个被SpringBoot自动装配的类,且 PageHelperAutoConfiguration 被 @ConditionalOnBean(SqlSessionFactory.class)  注解标识

  Step5: 在 SpringBootApplication 启动类的main方法结尾处打断点, 发现SpringContext中实际是存在SqlSessionFactory Bean的,由此推断问题出现在SpringBoot自动装配阶段,在AutoConfigurationImportSelector.getCandidateConfigurations() 方法内打断点,确认PageHelperAutoConfiguration不在待加载的configurations

  Step6: 回到SpringBoot源码,@SpringBootApplication -> @EnableAutoConfiguration -> @Import(AutoConfigurationImportSelector.class)

-> AutoConfigurationImportSelector.getCandidateConfigurations() ->ImportCandidates.load() 方法, 发现 ImportCandidates.LOCATION = "META-INF/spring/%s.imports" (SpringBootStarter 最新版)

  Step7: 查看 com.github.pagehelper.autoconfigure-1.4.0.jar下 /META-INF 文件夹 发现 EnableAutoConfiguration配置信息放在 spring.factories 文件内(SpringBootStarter 旧版本支持),与Step6中的ImportCandidates.LOCATION不匹配,导致 PageHelperAutoConfiguration类未被装载

 1 public final class ImportCandidates implements Iterable<String> {
 2 
 3     private static final String LOCATION = "META-INF/spring/%s.imports";
 4 
 5     public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
 6         Assert.notNull(annotation, "'annotation' must not be null");
 7         ClassLoader classLoaderToUse = decideClassloader(classLoader);
 8         String location = String.format(LOCATION, annotation.getName());
 9         
10         Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
11         List<String> importCandidates = new ArrayList<>();
12         while (urls.hasMoreElements()) {
13             URL url = urls.nextElement();
14             importCandidates.addAll(readCandidateConfigurations(url));
15         }
16         return new ImportCandidates(importCandidates);
17     }
18 }
View Code

  Step8: 在 maven 中央仓库中查找pagehelper最新版本(1.4.7),升级pagehelper依赖版本到最新版,检查com.github.pagehelper.autoconfigure-1.4.0.jar下/META-INF 文件夹/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,与ImportCandidates.LOCATION匹配! 重新测试代码,发现PageHelperAutoConfiguration装载成功,分页功能正常。

5、心得感悟:

  1、“内事不决问百度,外事不决问谷歌”, 出于赶项目工期等原因,一般在开发过程中遇到bug首先会去网上看有没有人遇到过同样的问题,有的话可以直接参考其原因及解决方案,没有的话再去打断点、分析源码

  2、To Be Honest, 对于各个框架的源码,我的学习方式也是直接在B站上先跟着专门做相关培训的老师后面先看一遍,因为他们投入了大量的时间整理出了阅读源码的核心思路,然后自己再参照视频实际看一下相关的源码,留一个大致的映像,在需要用到源码知识解决问题的时候再去源码中debug,有一种“且放白鹿青崖间,须行即骑访名山”的意思~

 

标签:1.4,SpringBoot,pagehelper,源码,PageHelperAutoConfiguration,class
From: https://www.cnblogs.com/sanbanfu-howie/p/17615172.html

相关文章

  • 在直播系统源码中接入谷歌支付
    支付在直播系统源码中有很重要的作用,在直播平台中,送礼物、买东西等很多功能都需要用到支付这个功能,支付方式上的接入服务也是越来越来,下面就给大家介绍下载直播系统源码中接入谷歌支付的过程。android同胞我相信很多人跟我一样谷歌支付运行自己的直播系统源码的时候调用支付发现......
  • fastapi后台任务模块<BackgroundTasks>源码理解
      该文档主要对fastapi的后台模块《BackgroundTasks》一些源码的理解,这样也可以加深理解异步及后台任务处理的理解。 使用导入例子: fromfastapiimport BackgroundTasks  fromfastapiimportBackgroundTasks,FastAPIapp=FastAPI()defwrite_file(data:st......
  • 智慧工地源码,基于Vue+Spring Cloud +UniApp框架开发
    源码技术架构:微服务+JavaVue+SpringCloud+UniApp+MySql智慧工地管理平台是依托物联网、互联网、AI、可视化建立的大数据管理平台,是一种全新的管理模式,能够实现劳务管理、安全施工、绿色施工的智能化和互联网化。智慧工地管理平台功能包括:劳务实名制管理系统、监测系统、区域安......
  • springboot设置log4j2无效
     log4j2需要在资源文件中正确的写法:错误的写法:下面写法会无效的会使用springboot本身的日志 ......
  • SpringBoot - Web项目起步
    环境搭建开发规范1开发规范2.1开发规范2.2开发规范2.3开发流程......
  • Bert Pytorch 源码分析:五、模型架构简图 REV1
    注意力FFNTF块整体架构......
  • 国标GB28181视频平台LntonGBS(源码版)国标平台级联时,通道上传上级宇视平台无法接收的问
    LntonGBS是基于公安部推出的GB/T28181协议开发的视频平台,在安防监控领域应用广泛。下面是一些关于LntonGBS平台的主要特点:GB/T28181协议兼容性、视频直播和转码、云端录像和存储、语音对讲和警告功能、平台级联功能。通过以上的功能和特点,LntonGBS平台能够满足安防监控领域各类场景......
  • 山东布谷科技直播程序源码使用Redis进行服务器横向扩展
    当今,直播程序源码平台作为新媒体时代主流,受到了世界各地人民的喜爱,这也使得直播程序源码平台用户数量的庞大,也难免会出现大量用户同时访问服务器,使服务器过载的情况,当服务器承受不住的时候,可能就会造成服务器崩溃,为了应对这一问题,直播程序源码的开发人员在开发服务器的时候就要去使......
  • 山东布谷科技直播程序源码使用Redis进行服务器横向扩展
    当今,直播程序源码平台作为新媒体时代主流,受到了世界各地人民的喜爱,这也使得直播程序源码平台用户数量的庞大,也难免会出现大量用户同时访问服务器,使服务器过载的情况,当服务器承受不住的时候,可能就会造成服务器崩溃,为了应对这一问题,直播程序源码的开发人员在开发服务器的时候就要去......
  • springboot不使用端口的方式启动
    SpringBoot项目不占用端口启动现在很多互联网公司或者项目,都使用SpringBoot+SpringCloud,以微服务的形式来提供后台服务。而且既然是微服务,所涉及到的项目就会很多,服务器端口资源就会相当紧张。而且,其实有些项目,如定时任务等,是不需要对外提供服务,也就不需要占用服务器端口的。......