Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
简介: 该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。

1.简单项目:

我这里有一个简单的Springboot的Web项目,需要添加Springboot整合mybatis或者是mybatisPlus的依赖,这里我就以mybatis为例了,mybatisPlus跟mybatis是差不多的,首先添加依赖:

xml

代码解读

复制代码

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

Springboot的主启动类:使用MapperScan注解配置了一个包扫描的路径。

less

代码解读

复制代码

@SpringBootApplication
@MapperScan("com.atlx")
public class Springboot2DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(Springboot2DemoApplication.class, args);
    }
}

如果我们不使用@MapperScan注解配置包扫描的路径的话,Springboot在启动的时候也会去扫描Mapper接口,但是扫描的路径跟Springboot启动扫描类生成BeanDefinition的路径是一样的,并且还只会去扫描加了@Mapper注解的类。但是如果我们使用了@MapperScan注解并且配置了扫描的路径的话那么Springboot就会根据我们配置的路径去扫描Mapper接口。

所以下面我们的分析就是根据有没有加@MapperScan注解来分析。

2.没有加@MapperScan注解:

如果一个Springboot项目中没有加@MapperScan注解的话,那么在扫描Mapper接口的时候Springboot回去扫描加了@Mapper注解的接口,下面我们通过源码进行分析:

首先在idea中找到Springboot整合mybatis的依赖包:

编辑

找到里面对应的spring.factories文件:

ini

代码解读

复制代码

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

它里面有对应的springboot整合mybatis的自动配置文件:MybatisAutoConfiguration,进入自动配置文件:里面有一个非常核心的内部类: MapperScannerRegistrarNotFoundConfiguration

less

代码解读

复制代码

    @Configuration
    @Import({AutoConfiguredMapperScannerRegistrar.class})
    @ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class})
    public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
        public MapperScannerRegistrarNotFoundConfiguration() {
        }

        public void afterPropertiesSet() {
            MybatisAutoConfiguration.logger.debug("Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");
        }
    }

很显然这个内部类是一个自动配置了,并且还使用了@Import注解导入了:AutoConfiguredMapperScannerRegistrar这个类,这个类就是自动扫描的核心类,下面进入这个类:

需要注意的是要想使用@Import生效,那么必须要满足上面的条件注解:Spring容器中没有:MapperFactoryBean和MapperScannerConfigurer

进入AutoConfiguredMapperScannerRegistrar这个类:这里我就截取部分源代码:

csharp

代码解读

复制代码

 public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, EnvironmentAware, ImportBeanDefinitionRegistrar {
        private BeanFactory beanFactory;
        private Environment environment;

        public AutoConfiguredMapperScannerRegistrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            if (!AutoConfigurationPackages.has(this.beanFactory)) {
                MybatisAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
            } else {
                MybatisAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");
                List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
                if (MybatisAutoConfiguration.logger.isDebugEnabled()) {
                    packages.forEach((pkg) -> {
                        MybatisAutoConfiguration.logger.debug("Using auto-configuration base package '{}'", pkg);
                    });
                }

                BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
                builder.addPropertyValue("processPropertyPlaceHolders", true);
                builder.addPropertyValue("annotationClass", Mapper.class);
                builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages));
                BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class);

显然这个类实现了:ImportBeanDefinitionRegistrar这个类,那么自然需要重写:registerBeanDefinitions()方法,自然核心逻辑就在这个方法中:

在源码中能够清楚的发现它在构建一个beanDefinition:而构建的类就是:MapperScannerConfigurer

ini

代码解读

复制代码

BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);

并且还对这个beanDefinition添加了一些属性:

vbscript

代码解读

复制代码

                builder.addPropertyValue("annotationClass", Mapper.class);
                builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages));

其中比较关键的就是添加了需要扫描的注解为:Mapper注解。

需要扫描的路径为:Springboot扫描bean的路径, 这里并不是直接写死的,而是通过一个工具类获取到的,而这个包路径则是在启动的时候在@SpringBootApplication这个注解的@EnableAutoConfiguration注解的@AutoConfigurationPackage注解中添加进去的。

并且它导入的MapperScannerConfigurer这个类它实现了:BeanDefinitionRegistryPostProcessor这个beanFactoryPostProcessor,那么自然就要重写postProcessBeanDefinitionRegistry()方法,而扫描的逻辑就是在这个方法中实现的,而这个方法的调用就是在Spring启动的Refresh()方法中的:invokeBeanFactoryPostProcessors(beanFactory);方法中。

到这里Springboot整合mybatis实现Mapper接口的自动扫描源码就分析结束了,下面我们看看加了@MapperScan注解的情况。

3.加了@MapperScan注解:

如果项目中加了@MapperScan注解,那么程序员自然就会去配置扫描的路径,而Springboot就会直接去扫描配置的这个路径:

下面我们直接进入@MapperScan()注解:

less

代码解读

复制代码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {

}

发现它也导入了:MapperScannerRegistrar这个类,那么其实现的逻辑跟上面的没有加@MapperScan注解的实现逻辑就是一样的了,只是扫描的包不一样而已。

4.总结:

在项目中使用MapperScan注解和不使用MapperScan注解其实区别不大,只是如果你不适应MapperScan注解的话,那么你需要对你的Mapper接口加上@Mapper注解那么Springboot才能够扫描到,如果你使用了@MapperScan注解的话,那么你只需要配置包路径即可。

注意:如果在项目中如果使用了@MapperScan注解的话,那么Springboot自动帮你扫描的那段逻辑也就是标题的第二点就不会生效了,因为我们看了它的源码,它那个内部类中有一个条件注解,其条件就是容器中不存在:MapperScannerRegistrar的话才会生效,显然当使用@MapperScan的时候也导入了MapperScannerRegistrar所以说容器中已经存在了,那么自动扫描那一套就自然不会生效,从而就不会导致重复扫描的问题了。

到这里不知道有没有一个疑问,就是:如果Springboot在启动的时候,先执行了Srpingboot的自动扫描,然后再执行了@MapperScan注解,这样的话也会导致扫描了两遍。其实不会的,它这里还是有一个优先级的, @MapperScan注解的优先级是大于Springboot的自动扫描。


转载来源:https://juejin.cn/post/7373306258404229129

相关文章
|
10月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
631 7
|
9月前
|
JavaScript 前端开发 Java
制造业ERP源码,工厂ERP管理系统,前端框架:Vue,后端框架:SpringBoot
这是一套基于SpringBoot+Vue技术栈开发的ERP企业管理系统,采用Java语言与vscode工具。系统涵盖采购/销售、出入库、生产、品质管理等功能,整合客户与供应商数据,支持在线协同和业务全流程管控。同时提供主数据管理、权限控制、工作流审批、报表自定义及打印、在线报表开发和自定义表单功能,助力企业实现高效自动化管理,并通过UniAPP实现移动端支持,满足多场景应用需求。
891 1
|
8月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
1403 1
Spring boot 使用mybatis generator 自动生成代码插件
|
10月前
|
前端开发 Java 物联网
智慧班牌源码,采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署
智慧班牌系统是一款基于信息化与物联网技术的校园管理工具,集成电子屏显示、人脸识别及数据交互功能,实现班级信息展示、智能考勤与家校互通。系统采用Java + Spring Boot后端框架,搭配Vue2前端技术,支持SaaS云部署与私有化定制。核心功能涵盖信息发布、考勤管理、教务处理及数据分析,助力校园文化建设与教学优化。其综合性和可扩展性有效打破数据孤岛,提升交互体验并降低管理成本,适用于日常教学、考试管理和应急场景,为智慧校园建设提供全面解决方案。
600 70
|
11月前
|
SQL XML Java
一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程
一、MyBatis简介:MyBatis历史、MyBatis特性、和其它持久化层技术对比、Mybatis下载依赖包流程
373 69
|
9月前
|
供应链 JavaScript BI
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
这是一款专为小微企业打造的 SaaS ERP 管理系统,基于 SpringBoot+Vue+ElementUI+UniAPP 技术栈开发,帮助企业轻松上云。系统覆盖进销存、采购、销售、生产、财务、品质、OA 办公及 CRM 等核心功能,业务流程清晰且操作简便。支持二次开发与商用,提供自定义界面、审批流配置及灵活报表设计,助力企业高效管理与数字化转型。
755 2
ERP系统源码,基于SpringBoot+Vue+ElementUI+UniAPP开发
|
8月前
|
SQL Java 数据库
解决Java Spring Boot应用中MyBatis-Plus查询问题的策略。
保持技能更新是侦探的重要素质。定期回顾最佳实践和新技术。比如,定期查看MyBatis-Plus的更新和社区的最佳做法,这样才能不断提升查询效率和性能。
401 1
|
8月前
|
机器学习/深度学习 数据采集 人机交互
springboot+redis互联网医院智能导诊系统源码,基于医疗大模型、知识图谱、人机交互方式实现
智能导诊系统基于医疗大模型、知识图谱与人机交互技术,解决患者“知症不知病”“挂错号”等问题。通过多模态交互(语音、文字、图片等)收集病情信息,结合医学知识图谱和深度推理,实现精准的科室推荐和分级诊疗引导。系统支持基于规则模板和数据模型两种开发原理:前者依赖人工设定症状-科室规则,后者通过机器学习或深度学习分析问诊数据。其特点包括快速病情收集、智能病症关联推理、最佳就医推荐、分级导流以及与院内平台联动,提升患者就诊效率和服务体验。技术架构采用 SpringBoot+Redis+MyBatis Plus+MySQL+RocketMQ,确保高效稳定运行。
637 0
|
11月前
|
小程序 Java 关系型数据库
weixin117新闻资讯系统设计+springboot(文档+源码)_kaic
本文介绍了一款基于微信小程序的新闻资讯系统,涵盖其开发全过程。该系统采用Java的SSM框架进行后台管理开发,使用MySQL作为本地数据库,并借助微信开发者工具确保稳定性。管理员可通过个人中心、用户管理等功能模块实现高效管理,而用户则能注册登录并查看新闻与视频内容。系统设计注重可行性分析(技术、经济、操作),强调安全性与数据完整性,界面简洁易用,功能全面,极大提升了信息管理效率及用户体验。关键词包括基于微信小程序的新闻资讯系统、SSM框架和MYSQL数据库。
|
12月前
|
小程序 JavaScript Java
基于SpringBoot的智慧停车场微信小程序源码分享
智慧停车场微信小程序主要包含管理端和小程序端。管理端包括停车场管理,公告信息管理,用户信息管理,预定信息管理,用户反馈管理等功能。小程序端包括登录注册,预约停车位,停车导航,停车缴费,用户信息,车辆信息,钱包充值,意见反馈等功能。
571 5
基于SpringBoot的智慧停车场微信小程序源码分享