mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比,于是写了个插件。 (3)

简介: mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比,于是写了个插件。 (3)

mybatis插件的原理


前面我们知道拦截器怎么写了,接下来简单的分析一波原理。


前几天我看到一个观点是说看开源框架的源码建议从 mybatis 看起。我是很赞成这个观点的,确实是优雅,而容易看懂。能品出很多设计模式的使用。


一句话总结 mybatis插件的原理就是:动态代理加上责任链。


先看一下 Plugin 类的动态代理:


标号为 ① 的地方一看就知道,InvocationHandler,JDK 动态代理,没啥说的。

标号为 ② 的地方是 wrap 方法,生成 Plugin 代理对象。


标号为 ③ 的地方是 invoker 方法,圈起来的目的是想说是在这里判断当前方法是否是需要被拦截的方法。如果是则用代理对象走拦截器逻辑,如果不是则用目标对象,走正常逻辑。


给大家看一下这个地方的 debug 效果:


一个平平无奇的 if 判断,是拦截器的关键。为什么这个地方多说了几句呢?


因为其实这就是细节的地方。当面试的时候面试官问你:mybatis 是怎么判断是否需要拦截这个方法的时候你能答上来。说明你是真的看过源码。

责任链是怎么体现的呢?


就是这个地方: org.apache.ibatis.plugin.InterceptorChain


你看又学到一招,mybatis 里面的设计模式还有责任链。

我们看一下 pluginAll 方法的调用方:


这个地方就体现出之前官网说的了:

插件是作用于这四大对象的:Executor、ParameterHandler 、ResultSetHandler 、StatementHandler 。


上面框起来的这四个框,就是插件调用的地方。


那么插件在什么时候被加载,或者说什么是被注册上的呢?

还是回到拦截链这个类上去:


pluginAll 方法我们已经知道有哪些地方调用了。这个方法里面其实还有两个考点。


第一就是 interceptor 这个 List 集合的定义,用了 final 修饰。所以要注意 final 修饰基本类型和引用类型的区别,被 final 修饰的引用类型变量内部的内容是可以发生变化的。


第二就是 getInterceptors 返回的是一个不可修改的 List 。所以,要对集合 interceptors 进行修改,只能通过 addInterceptor 方法进行元素添加,保证了这个集合是可控的。

所以,我们只需要知道哪里调用了 addInterceptor 方法,哪里就是插件被注册的地方。



一个是 SqlSessionFactoryBean ,一个是 XMLConfigBuilder。

使用 XML 配置是这样的:


熟悉 mybatis 的朋友们肯定知道,无非就是对于标签的解析而已。


解析到 plugins 标签,则进入 pluginElement 方法中,在这个方法里面调用 addInterceptor:


本文没有使用 XML 的形式配置,所以我们主要看一下 SqlSessionFactoryBean。

怎么看呢?


不要盲目的走入源码,加个断点看调用链,跟着调用链去走就很清晰了。

在这个地方加一个断点:


然后 debug 起来,你就可以看到整个调用链了:


然后我们根据上面的调用链,我们就可以找到源头了:


在 MybatisAutoConfiguration 的构造方法里面初始化了 interceptors。

而 interceptorsProvider.getIfAvailable() 方法也解释了为什么我们只需要在程序里面这样注入我们的拦截器就可以被找到了:


对 getIfAvailable 方法不熟悉的朋友可以去补一下这块的知识,我这里只是给大家看一下这个方法上的注释:


当然,你这样去注入的话有可能会不生效,你就会大骂一声:写的什么垃圾玩意,配置上了也不对呀。


别着急呀,我还没说完呢。你看看是不是有自定义的 SqlSessionFactory 在项目里。

看一下注入 SqlSessionFactory 的源码上面的那个注解了吗?


@ConditionalOnMissingBean ,看名字也知道了,当你的项目里面没有自定义的 SqlSessionFactory 的时候,才会由源码给你注入,这个时候才会正在的注册上插件:


如果你有自定义的 SqlSessionFactory,那么请手动调用 factory.setPlugins 方法。

所以,总结一下插件的三种配置方法:


1.xml方式配置。


2.如果没有自定义 SqlSessionFactory 直接 @Bean 注入拦截器即可。


3.如果有自定义 SqlSessionFactory 需要在自定义的地方手动调用 factory.setPlugins 方法。


其实我尝试过第四种方法,在application.properties 里面配置:


这种配置方式才是符合 SpringBoot 思想的配置。才是真正的丝滑,润物无声的丝滑。


可惜,我配置上后,点击到对应的源码地方一看:


它调用的是 getInterceptors 方法,我就知道肯定是有问题了:


果然,运行起来会报这样的错误: Failed to bind properties under 'mybatis.configuration.interceptors' to java.util.List<org.apache.ibatis.plugin.Interceptor>

找了一圈原因,最后发现了这个 issue:


github.com/mybatis/spring-boot-starter/issues/180

这个“奇异博士”头像的用户提出了和我一样的问题:


然后下面的回答是这样的:


别问,问就是不支持。请使用 @Bean 的方式。


最后说一句(求关注)


点个“赞”吧,周更很累的,不要白嫖我,需要一点正反馈。


才疏学浅,难免会有纰漏,如果你发现了错误的地方,还请你指出来,我对其加以修改。

感谢您的阅读,我坚持原创,十分欢迎并感谢您的关注。


我是 why,一个被代码耽误的文学创作者,不是大佬,但是喜欢分享,是一个又暖又有料的四川好男人。


欢迎关注我的微信公众号:why技术。在这里我会分享一些java技术相关的知识,用匠心敲代码,对每一行代码负责。偶尔也会荒腔走板的聊一聊生活,写一写书评、影评。感谢你的关注,愿你我共同进步。


目录
相关文章
|
4月前
|
SQL XML Java
8、Mybatis-Plus 分页插件、自定义分页
这篇文章介绍了Mybatis-Plus的分页功能,包括如何配置分页插件、使用Mybatis-Plus提供的Page对象进行分页查询,以及如何在XML中自定义分页SQL。文章通过具体的代码示例和测试结果,展示了分页插件的使用和自定义分页的方法。
8、Mybatis-Plus 分页插件、自定义分页
|
1月前
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
166 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
24天前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
1月前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
16天前
|
Java 数据库连接 数据库
spring和Mybatis的逆向工程
通过本文的介绍,我们了解了如何使用Spring和MyBatis进行逆向工程,包括环境配置、MyBatis Generator配置、Spring和MyBatis整合以及业务逻辑的编写。逆向工程极大地提高了开发效率,减少了重复劳动,保证了代码的一致性和可维护性。希望这篇文章能帮助你在项目中高效地使用Spring和MyBatis。
10 1
|
2月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
130 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
3月前
|
SQL Java 数据库连接
解决mybatis-plus 拦截器不生效--分页插件不生效
本文介绍了在使用 Mybatis-Plus 进行分页查询时遇到的问题及解决方法。依赖包包括 `mybatis-plus-boot-starter`、`mybatis-plus-extension` 等,并给出了正确的分页配置和代码示例。当分页功能失效时,需将 Mybatis-Plus 版本改为 3.5.5 并正确配置拦截器。
873 6
解决mybatis-plus 拦截器不生效--分页插件不生效
|
3月前
|
SQL XML Java
springboot整合mybatis-plus及mybatis-plus分页插件的使用
这篇文章介绍了如何在Spring Boot项目中整合MyBatis-Plus及其分页插件,包括依赖引入、配置文件编写、SQL表创建、Mapper层、Service层、Controller层的创建,以及分页插件的使用和数据展示HTML页面的编写。
springboot整合mybatis-plus及mybatis-plus分页插件的使用
|
2月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
65 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
2月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
441 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个