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

MybatisPlusAutoConfiguration源码阅读

代码如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package com.baomidou.mybatisplus.autoconfigure;import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import java.util.Iterator;
import java.util.List;
import javax.sql.DataSource;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.ClassPathMapperScanner;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties({MybatisPlusProperties.class})
@AutoConfigureAfter({DataSourceAutoConfiguration.class})
public class MybatisPlusAutoConfiguration implements InitializingBean {private static final Logger logger = LoggerFactory.getLogger(MybatisPlusAutoConfiguration.class);private final MybatisPlusProperties properties;private final Interceptor[] interceptors;private final ResourceLoader resourceLoader;private final DatabaseIdProvider databaseIdProvider;private final List<ConfigurationCustomizer> configurationCustomizers;private final ApplicationContext applicationContext;public MybatisPlusAutoConfiguration(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider, ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider, ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider, ApplicationContext applicationContext) {this.properties = properties;this.interceptors = (Interceptor[])interceptorsProvider.getIfAvailable();this.resourceLoader = resourceLoader;this.databaseIdProvider = (DatabaseIdProvider)databaseIdProvider.getIfAvailable();this.configurationCustomizers = (List)configurationCustomizersProvider.getIfAvailable();this.applicationContext = applicationContext;}public void afterPropertiesSet() {this.checkConfigFileExists();}private void checkConfigFileExists() {if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());Assert.state(resource.exists(), "Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");}}@Bean@ConditionalOnMissingBeanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();factory.setDataSource(dataSource);factory.setVfs(SpringBootVFS.class);if (StringUtils.hasText(this.properties.getConfigLocation())) {factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));}this.applyConfiguration(factory);if (this.properties.getConfigurationProperties() != null) {factory.setConfigurationProperties(this.properties.getConfigurationProperties());}if (!ObjectUtils.isEmpty(this.interceptors)) {factory.setPlugins(this.interceptors);}if (this.databaseIdProvider != null) {factory.setDatabaseIdProvider(this.databaseIdProvider);}if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());}if (this.properties.getTypeAliasesSuperType() != null) {factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());}if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());}if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {factory.setMapperLocations(this.properties.resolveMapperLocations());}if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());}GlobalConfig globalConfig = this.properties.getGlobalConfig();if (this.applicationContext.getBeanNamesForType(MetaObjectHandler.class, false, false).length > 0) {MetaObjectHandler metaObjectHandler = (MetaObjectHandler)this.applicationContext.getBean(MetaObjectHandler.class);globalConfig.setMetaObjectHandler(metaObjectHandler);}if (this.applicationContext.getBeanNamesForType(IKeyGenerator.class, false, false).length > 0) {IKeyGenerator keyGenerator = (IKeyGenerator)this.applicationContext.getBean(IKeyGenerator.class);globalConfig.getDbConfig().setKeyGenerator(keyGenerator);}if (this.applicationContext.getBeanNamesForType(ISqlInjector.class, false, false).length > 0) {ISqlInjector iSqlInjector = (ISqlInjector)this.applicationContext.getBean(ISqlInjector.class);globalConfig.setSqlInjector(iSqlInjector);}factory.setGlobalConfig(globalConfig);return factory.getObject();}private void applyConfiguration(MybatisSqlSessionFactoryBean factory) {MybatisConfiguration configuration = this.properties.getConfiguration();if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {configuration = new MybatisConfiguration();}if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {Iterator var3 = this.configurationCustomizers.iterator();while(var3.hasNext()) {ConfigurationCustomizer customizer = (ConfigurationCustomizer)var3.next();customizer.customize(configuration);}}factory.setConfiguration(configuration);}@Bean@ConditionalOnMissingBeanpublic SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {ExecutorType executorType = this.properties.getExecutorType();return executorType != null ? new SqlSessionTemplate(sqlSessionFactory, executorType) : new SqlSessionTemplate(sqlSessionFactory);}@Configuration@Import({AutoConfiguredMapperScannerRegistrar.class})@ConditionalOnMissingBean({MapperFactoryBean.class})public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {public MapperScannerRegistrarNotFoundConfiguration() {}public void afterPropertiesSet() {MybatisPlusAutoConfiguration.logger.debug("No {} found.", MapperFactoryBean.class.getName());}}public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {private BeanFactory beanFactory;private ResourceLoader resourceLoader;public AutoConfiguredMapperScannerRegistrar() {}public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {if (!AutoConfigurationPackages.has(this.beanFactory)) {MybatisPlusAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");} else {MybatisPlusAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");List<String> packages = AutoConfigurationPackages.get(this.beanFactory);if (MybatisPlusAutoConfiguration.logger.isDebugEnabled()) {packages.forEach((pkg) -> {MybatisPlusAutoConfiguration.logger.debug("Using auto-configuration base package '{}'", pkg);});}ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);if (this.resourceLoader != null) {scanner.setResourceLoader(this.resourceLoader);}scanner.setAnnotationClass(Mapper.class);scanner.registerFilters();scanner.doScan(StringUtils.toStringArray(packages));}}public void setBeanFactory(BeanFactory beanFactory) {this.beanFactory = beanFactory;}public void setResourceLoader(ResourceLoader resourceLoader) {this.resourceLoader = resourceLoader;}}
}

一.注解分析

1.@Configuration

 该类是一个配置类

2.@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})

 SqlSessionFactory和SqlSessionFactoryBean两个类必须存在

3. @ConditionalOnSingleCandidate(DataSource.class)

 DataSource类只有一个类型,确保单一数据源

4.@EnableConfigurationProperties({MybatisPlusProperties.class})

 通过MybatisPlusProperties导入自动配置

 该类如下:

          通过配置文件进行数据绑定。下面是一个项目中的数据库的配置文件

# MyBatis-Plus配置
# 配置Mapper XML文件的扫描路径,支持通配符匹配多个路径下的Mapper文件
mybatis-plus.mapper-locations: classpath*:/mapper/*Mapper.xml# 实体扫描,多个 package 用逗号或者分号分隔
mybatis-plus.typeAliasesPackage: com.test.common.*.entity# 数据库相关配置
# 主键类型  AUTO:"数据库ID自增", INPUT:"用户输入ID",ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
mybatis-plus.global-config.db-config.id-type: AUTO# 字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断"
mybatis-plus.global-config.db-config.field-strategy: not_empty# 驼峰下划线转换
mybatis-plus.global-config.db-config.column-underline: true# 数据库大写下划线转换
#mybatis-plus.global-config.db-config.capital-mode: true# 逻辑删除配置
# 逻辑删除的值,当记录被逻辑删除时,数据库字段将被设置为该值
mybatis-plus.global-config.db-config.logic-delete-value: 0
# 逻辑未删除的值,表示记录未被删除时数据库字段的值
mybatis-plus.global-config.db-config.logic-not-delete-value: 1# 刷新 mapper
mybatis-plus.global-config.refresh: false# 是否显示MyBatis-Plus启动时的banner信息
mybatis-plus.global-config.banner: false

上面以mybatis-plus为前缀的属性值会和MybatisPlusProperties中的配置类中的属性进行绑定。

5.@AutoConfigureAfter({DataSourceAutoConfiguration.class})

       该类会在DataSourceAutoConfiguration类配置后在进行配置,确保配置顺序正确,在数据源配置加载之后再加载数据库配置。

二.代码核心思路分析

1. 该类实现了Spring框架的InitializingBean接口,

  在afterPropertiesSet()初始化方法里面使用checkConfigFileExists()方法校验配置文件是否存在。

2.缺失类的自动配置

如果SqlSessionFactory,SqlSessionTemplate类缺失会自动配置

 @Bean@ConditionalOnMissingBeanpublic SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
 @Bean@ConditionalOnMissingBeanpublic SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {

3.使用配置

应用MyBatis配置到SqlSessionFactoryBean中,如果有定制化配置使用定制化的配置。

4.处理缺失MapperFactoryBean类的场景

当缺失MapperFactoryBean类(MapperFactoryBean类用于创建MyBatis的Mapper接口代理实例),使用@Import({AutoConfiguredMapperScannerRegistrar.class})导入注册类。AutoConfiguredMapperScannerRegistrar负责自动扫描和注册MyBatis的Mapper接口。

    /*** 自动配置的Mapper扫描注册器* 实现BeanFactoryAware、ImportBeanDefinitionRegistrar和ResourceLoaderAware接口,* 用于自动扫描和注册标记了@Mapper注解的Mapper接口*/public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {private BeanFactory beanFactory;private ResourceLoader resourceLoader;public AutoConfiguredMapperScannerRegistrar() {}/*** 注册Bean定义,扫描并注册Mapper接口* @param importingClassMetadata 导入类的元数据信息* @param registry Bean定义注册器*/public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 检查是否存在自动配置包,如果不存在则禁用自动Mapper扫描if (!AutoConfigurationPackages.has(this.beanFactory)) {MybatisPlusAutoConfiguration.logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");} else {MybatisPlusAutoConfiguration.logger.debug("Searching for mappers annotated with @Mapper");List<String> packages = AutoConfigurationPackages.get(this.beanFactory);if (MybatisPlusAutoConfiguration.logger.isDebugEnabled()) {packages.forEach((pkg) -> {MybatisPlusAutoConfiguration.logger.debug("Using auto-configuration base package '{}'", pkg);});}// 创建类路径Mapper扫描器并进行配置ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);if (this.resourceLoader != null) {scanner.setResourceLoader(this.resourceLoader);}// 设置要扫描的注解类型为@Mapper,并执行扫描scanner.setAnnotationClass(Mapper.class);scanner.registerFilters();scanner.doScan(StringUtils.toStringArray(packages));}}/*** 设置Bean工厂* @param beanFactory Bean工厂实例*/public void setBeanFactory(BeanFactory beanFactory) {this.beanFactory = beanFactory;}/*** 设置资源加载器* @param resourceLoader 资源加载器实例*/public void setResourceLoader(ResourceLoader resourceLoader) {this.resourceLoader = resourceLoader;}}

http://www.xdnf.cn/news/18312.html

相关文章:

  • 强化学习算法分类与介绍(含权重更新公式)
  • 深度解析Atlassian 团队协作套件(Jira、Confluence、Loom、Rovo)如何赋能全球分布式团队协作
  • Windows查看端口占用情况
  • 2025年物流大数据分析的主要趋势
  • 【LeetCode 热题 100】322. 零钱兑换——(解法二)自底向上
  • 嵌入式接口通识知识之SDIO接口
  • 聚铭安全管家平台2.0实战解码 | 安服篇(四):重构威胁追溯体系
  • 手写MyBatis第28弹:告别代理,直击本质:手写MyBatis SqlSession的增删改查奥秘
  • 「数据获取」《中国环境统计年鉴》(1998-2024)(获取方式看绑定的资源)
  • C# 编写一个XmlToDota的转换工具
  • Seaborn数据可视化实战:Seaborn入门-环境搭建与基础操作
  • [ Servlet 服务器]
  • electron-vite_18Less和Sass共用样式指定
  • 基于混合注意力网络和深度信念网络的鲁棒视频水印技术基础理论深度解析
  • AI设计师-标小智旗下AI在线设计平台
  • [论文阅读] 人工智能 + 软件工程 | 当AI成为文学研究员:Agentic DraCor如何用MCP解锁戏剧数据分析
  • 设计模式之观察者模式
  • 为什么可以kvcache
  • 订单簿数据深度学习方法在大单发现应用
  • 微信小程序集成vant-weapp时,构建npm报错的解决办法
  • 深度学习-计算机视觉-物体检测与边缘框实现
  • 区块链联邦学习思路一
  • 机器学习两大核心算法:集成学习与 K-Means 聚类详解
  • 如何保证数据库和缓存的一致性?
  • Java设计模式-模板方法模式
  • 常见开源协议详解:哪些行为被允许?哪些被限制?
  • B站 韩顺平 笔记 (Day 24)
  • K8S-Secret资源对象
  • 学习数组①
  • 1.Shell脚本修炼手册之---为什么要学Shell编程?