Spring Boot 集成Mybatis,@MapperScan不能解析占位符问题

MyBatis核心原理与Spring Boot集成实战:从SQL映射到动态查询 在Java后端开发中,数据持久化是构建稳定应用的核心基础。从最基础的JDBC手动处理连接与结果集,到ORM框架对对象关系映射的抽象,开发者始终在追求效率与灵活性的平衡。MyBatis作为一种半自动化的持久层框架,其核心价值在于将SQL的控制权交还给开发者,同时通过参数映射、结果集映射等机制大幅简化了数据库操作。它通过XML或注解配置实现SQL与Java代码的解耦,支持动态SQL构建,并能与Spring生态无缝集成,极大地提升了工程实践中的开发效率和代码可维护性。这种设计使其特别适用于对SQL优化有较高要求、 阅读详情

问题描述

Mybatis的@MapperScan中的basePackages属性值,只能获取到系统的占位符,不能获取到Application.properties定义的占位符

原因

@MapperScan 的处理类 MapperScannerRegistrar
MapperScannerRegistrar.registerBeanDefinitions()
-> new ClassPathMapperScanner(registry)
-> super(registry, false)
-> this(registry, useDefaultFilters, getOrCreateEnvironment(registry))
->

private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry instanceof EnvironmentCapable) {
            return ((EnvironmentCapable) registry).getEnvironment();
        }
        return new StandardEnvironment();
    }

这里的registry 不是EnvironmentCapable,所以生成了一个新的环境类

解决

创建ExpandMapperScan

和 @MapperScan 的属性一样只是改变 @Import(ExpandMapperScannerRegistrar.class)

import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.Import;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(ExpandMapperScannerRegistrar.class)
public @interface ExpandMapperScan {

    /**
     * Alias for the {@link #basePackages()} attribute. Allows for more concise
     * annotation declarations e.g.:
     * {@code @EnableMyBatisMapperScanner("org.my.pkg")} instead of {@code
     * @EnableMyBatisMapperScanner(basePackages= "org.my.pkg"})}.
     */
    String[] value() default {};

    /**
     * Base packages to scan for MyBatis interfaces. Note that only interfaces
     * with at least one method will be registered; concrete classes will be
     * ignored.
     */
    String[] basePackages() default {};

    /**
     * Type-safe alternative to {@link #basePackages()} for specifying the packages
     * to scan for annotated components. The package of each class specified will be scanned.
     * <p>Consider creating a special no-op marker class or interface in each package
     * that serves no purpose other than being referenced by this attribute.
     */
    Class<?>[] basePackageClasses() default {};

    /**
     * The {@link BeanNameGenerator} class to be used for naming detected components
     * within the Spring container.
     */
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    /**
     * This property specifies the annotation that the scanner will search for.
     * <p>
     * The scanner will register all interfaces in the base package that also have
     * the specified annotation.
     * <p>
     * Note this can be combined with markerInterface.
     */
    Class<? extends Annotation> annotationClass() default Annotation.class;

    /**
     * This property specifies the parent that the scanner will search for.
     * <p>
     * The scanner will register all interfaces in the base package that also have
     * the specified interface class as a parent.
     * <p>
     * Note this can be combined with annotationClass.
     */
    Class<?> markerInterface() default Class.class;

    /**
     * Specifies which {@code SqlSessionTemplate} to use in the case that there is
     * more than one in the spring context. Usually this is only needed when you
     * have more than one datasource.
     */
    String sqlSessionTemplateRef() default "";

    /**
     * Specifies which {@code SqlSessionFactory} to use in the case that there is
     * more than one in the spring context. Usually this is only needed when you
     * have more than one datasource.
     */
    String sqlSessionFactoryRef() default "";

    /**
     * Specifies a custom MapperFactoryBean to return a mybatis proxy as spring bean.
     *
     */
    Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;

}

ExpandMapperScannerRegistrar

和MapperScannerRegistrar 内容一样,只是在创建ClassPathMapperScanner时,手动注入Environment

import org.mybatis.spring.mapper.ClassPathMapperScanner;
import org.mybatis.spring.mapper.MapperFactoryBean;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;

public class ExpandMapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware{

    private ResourceLoader resourceLoader;
    Environment environment;
    /**
     * {@inheritDoc}
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(ExpandMapperScan.class.getName()));


        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        // 手动注入环境变量
        scanner.setEnvironment(environment);
        // this check is needed in Spring 3.1
        if (resourceLoader != null) {
            scanner.setResourceLoader(resourceLoader);
        }

        Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
        if (!Annotation.class.equals(annotationClass)) {
            scanner.setAnnotationClass(annotationClass);
        }

        Class<?> markerInterface = annoAttrs.getClass("markerInterface");
        if (!Class.class.equals(markerInterface)) {
            scanner.setMarkerInterface(markerInterface);
        }

        Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
        if (!BeanNameGenerator.class.equals(generatorClass)) {
            scanner.setBeanNameGenerator(BeanUtils.instantiateClass(generatorClass));
        }

        Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
        if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
            scanner.setMapperFactoryBean(BeanUtils.instantiateClass(mapperFactoryBeanClass));
        }

        scanner.setSqlSessionTemplateBeanName(annoAttrs.getString("sqlSessionTemplateRef"));
        scanner.setSqlSessionFactoryBeanName(annoAttrs.getString("sqlSessionFactoryRef"));

        List<String> basePackages = new ArrayList<String>();
        for (String pkg : annoAttrs.getStringArray("value")) {
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }
        for (String pkg : annoAttrs.getStringArray("basePackages")) {
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }
        for (Class<?> clazz : annoAttrs.getClassArray("basePackageClasses")) {
            basePackages.add(ClassUtils.getPackageName(clazz));
        }
        scanner.registerFilters();
        scanner.doScan(StringUtils.toStringArray(basePackages));
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }
}

具体如何解析占位符,可以自行跟踪源码,这里就不描述了

吃透MyBatis底层原理:从JDBC封装到Spring Boot整合实战 MyBatis本质是对JDBC使用模式的标准化封装,其核心在于将SQL执行抽象为SqlSession工作单元、Mapper动态代理与配置驱动的执行链路。理解其原理需回归JDBC原始痛点——参数绑定脆弱、结果映射冗余、资源管理易错,进而掌握SqlSession生命周期、Executor执行器机制及XML与注解双轨制的工程权衡。技术价值体现在提升SQL可治理性、支持插件化横切(如分页/日志)、实现线程安全的数据库会话隔离;典型应用场景包括Spring Boot中多数据源路由、二级缓存集成Redis、动态SQL精 阅读详情

相关推荐

从Spring Boot到MyBatis-Plus:一份druid.properties配置如何搞定多框架集成(避坑指南)

本文详细介绍了如何通过一份通用的druid.properties配置文件,高效集成Spring Boot和MyBatis-Plus框架,解决配置冲突、监控面板访问和多数据源管理等常见问题。文章提供了基础配置模板、Spring Boot集成技巧、MyBatis-Plus多数据源实战方案以及生产环境高级配置建议,帮助开发者快速避坑并优化数据库连接池性能。

758

Cannot resolve symbol ‘MapperScan‘ (整合Mybatis-plus)

Cannot resolve symbol 'MapperScan' (整合Mybatis-plus)

weixin_43783497的博客 2966

MyBatis核心解析:从SQL映射到高性能Java数据库操作实践

在Java企业级开发中,持久层框架是连接应用与数据库的关键组件,其核心价值在于简化数据访问逻辑并提升开发效率。MyBatis作为一款半自动化的SQL映射框架,通过将SQL语句与Java代码解耦,实现了灵活性与控制力的平衡。其工作原理基于JDBC封装,通过XML或注解配置SQL映射,自动处理参数设置与结果集封装,显著减少了冗余代码。这一技术方案特别适用于需要精细控制SQL、追求高性能的复杂查询场景,例如电商交易系统与金融数据处理平台。在实际工程实践中,MyBatis的动态SQL能力与批量操作优化,能够有效应对

weixin_34268310的博客 365

SpringBoot@Mapper和@MapperScan注解无法扫描到这个注解

最開始用的是是這個起步以來,用不了@Mapper和@MapperScan注解 &lt;!--mybatis起步依赖--&gt; &lt;dependency&gt; &lt;groupId&gt;org.mybatis.spring.boot&lt;/groupId&gt; &lt;artifactId&gt;mybatis-spring-boot-starter&lt;/art...

qq_37776884的博客 2万+

深入MyBatis源码:从核心原理到插件扩展的实战解析

在Java持久层开发中,ORM框架是连接应用程序与数据库的关键桥梁,其核心价值在于简化数据操作、提升开发效率并保障数据安全。MyBatis作为一款主流的半自动化ORM框架,通过将SQL与Java代码解耦,提供了灵活的映射机制和动态SQL功能。理解其底层原理,对于解决实际开发中的复杂问题至关重要。MyBatis的架构围绕SqlSession、Executor和StatementHandler等核心组件构建,采用动态代理机制实现Mapper接口的绑定,并通过插件体系支持功能扩展。例如,插件机制基于责任链模式,允

334

MyBatis核心原理与高级应用实战指南

MyBatis作为Java生态中主流的持久层框架,通过SQL映射与动态SQL机制实现了数据库操作的高效控制。其核心原理基于JDBC封装,提供XML/注解两种配置方式,在保持SQL可见性的同时显著提升开发效率。技术价值体现在灵活的结果集映射、可插拔的插件体系以及多级缓存设计,特别适合需要精细控制SQL的企业级应用场景。在Spring Boot集成实践中,通过mybatis-spring-boot-starter简化配置,结合动态SQL处理复杂查询条件,利用ResultMap实现对象关系映射。性能优化方面需关注

weixin_30855099的博客 422

VUE项目中使用this.$forceUpdate();解决页面v-for中修改item属性值后页面v-if不改变的问题

转载

木贝西的博客 445

Idea如何去除Mapper警告方法解析

主要介绍了Idea如何去除Mapper 警告的方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

记录一个关于@Mapper注解无效@MapperScan注解出错的问题

记录一个困扰我很久的问题 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'convertFileMapper' defined in file [D:\Documents\Desktop\ending\backstage-graduation\tar...

fanr639的博客 4207

linux离线安装nginx

linux离线安装nginx

zhang_130914036的博客 9347

Chapter 5 Gate Drivers and Level Shifters

Gate driver如下图所示, 包括功率管(带保护), Gate driver, Level shifter, Gate Supply 和Dead-time control.

2304_76736886的博客 2237

MyBatis-Spring Mapper自动扫描机制揭秘:@MapperScan注解的完整使用手册

🚀 **快速掌握MyBatis-Spring集成框架中最重要的自动配置神器!** 在Spring Boot和MyBatis集成的开发中,`@MapperScan`注解是实现Mapper自动注册的终极利器。通过本文,你将彻底理解这个强大注解的工作原理和最佳实践。💡 MyBatis-Spring集成框架中的`@MapperScan`注解是Spring 3.1+环境下配置MyBatis映射器的首选

gitblog_00994的博客 661

生信分析服务MR孟德尔随机化单细胞测序转录组数据分析网络药理学

通过上述技术整合,可实现从基因-环境-疾病关联到药物机制解析的全链条研究,为疾病机制解析和药物研发提供新思路。结合,是当前生物信息学领域的前沿方法,尤其在疾病机制解析、靶点发现和药物研发中展现出巨大潜力。

matlabgoodboy的博客 1520

Spring Boot + MyBatis服务启动流程,新增代码跑通流程,映射规则,常见问题定位

在 Spring Boot + MyBatis 注解/XML 混合开发中,大多数情况下,MyBatis 通过反射或 @Param 注解能自动推断参数类型,不需要显式写 parameterType,仅在遇到参数为 null 导致异常或使用旧版 MyBatis 时,才显式指定。MyBatis 中的 一对一()、一对多()、多对多(通常拆解为两个一对多) 映射,其本质就是 将 SQL 查询返回的扁平结果集(多表连接后的表状数据)转换为 Java 对象图。方式二: 多个参数,必须使用 @Param。

m0_49882060的博客 612

脑肿瘤MRI图像分割实战:基于U-Net的深度学习完整指南

脑肿瘤是中枢神经系统最常见的疾病之一,全球每年有超过30万人被诊断为原发性脑肿瘤。在临床诊断和治疗过程中,磁共振成像(MRI)已成为评估脑肿瘤的标准影像学检查方法。然而,手动分割MRI图像中的肿瘤区域是一项耗时且依赖于专家经验的工作,不同医生之间可能存在显著差异。

YOLO 151

基于STM32设计的猪舍养殖的监控系统_325

本课题基于STM32单片机,设计一款能够实时监测猪舍环境的智能监控系统。该系统能够通过温湿度、空气质量、光照强度等传感器实时监测猪舍的环境,并能够通过自动化控制设备(如风扇、照明灯、消毒喷雾等)调节环境参数,确保养殖环境的适宜性。同时,系统还支持通过ESP8266模块实现数据上传与远程控制,使养殖管理者能够通过手机APP或计算机远程监控和控制猪舍环境。

408

MyBatis

mybatis、mybatis-spring、mybatis-springboot源码学习

parkerJ 641

Unity开发抖音小游戏存储的几种方法分析

前段时间写小游戏为了省事一直就没有研究抖音小游戏的存储方案,一直使用的是unity中的PlayerPrefs去做的存储,但是后来发现官方会一直提醒让使用抖音sdk中的新文件存储系统,从而降低内存占用。

类人_猿的博客 2533

《Java 100 天进阶之路》第86篇:MyBatis 核心原理与缓存避坑指南(2026版)

从传统 XML 到 Spring Boot 自动装配,从 #{} 防注入到动态 SQL 解析,从一级缓存陷阱到二级缓存脏读,从原生 MyBatis 到 MyBatis-Plus 效率翻倍。本文深入剖析核心组件(SqlSession、Executor、StatementHandler)、执行流程、注解开发,并结合 MyBatis-Plus 分页插件与代码生成器,助你掌握 2026 年企业级持久层框架首选方案。面试必考 + 实战避坑,一篇通透。

折哥|智能物流与Java实战,副高数据库工程师。深耕出版社物流WMS/OMS(线体/立库/VGA),也分享Java进阶与OMS电商对接。Oracle→PG实战派。相信沉淀可迁移能力,分享通用技术,不藏不虚。 6238

C# 开发实战:深度解析 13.56MHz 射频卡读写应用

本文详细介绍了如何在 C# 环境下开发 13.56MHz 射频卡的读写应用。通过 ACR122U 作为硬件设备,结合 C# 提供的 COM 组件或 SDK,我们能够实现对射频卡的读取与写入功能。在实际开发中,开发者还需要根据具体应用场景选择合适的卡片类型与设备,并注意性能优化和异常处理。随着技术的发展,RFID 技术的应用场景会越来越广泛,开发者可以根据不同需求,灵活扩展读写功能,实现更加智能化和自动化的系统。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1602

【WLAN】【调试】再谈如何使用Wireshark解密WiFi数据包——使用TK信息

- 本文介绍了一种wireshark使用TK信息解密空口报文的方式,该方式对是否有关联过程的报文没有要求。

一介草民,只为生活。 1188

[特殊字符] MyBatis Mapper动态代理机制深度解析

摘要: MyBatis通过动态代理机制优化了传统JDBC操作数据库的繁琐流程,开发者仅需定义Mapper接口即可实现SQL执行。其核心组件(如SqlSession、Executor等)协作完成代理对象的创建与SQL路由:通过MapperProxyFactory生成代理,MapperProxy.invoke()拦截方法调用并交由MapperMethod执行具体SQL操作。Spring Boot中通过@MapperScan自动注册Mapper接口,结合MapperFactoryBean实现代理注入。MyBati

油墨香^-^的博客 395

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

MyBatis-Spring 快速入门指南

MyBatis-Spring官方文档入门指南介绍了如何将MyBatis集成到Spring项目中。核心步骤包括:1)配置SqlSessionFactory作为Spring Bean;2)将Mapper接口注册为Spring Bean,通过动态代理实现数据库操作。关键优势在于自动管理数据库连接、支持Spring事务和统一异常处理。整个过程通过FactoryBean机制在容器启动时完成初始化,业务层可直接注入Mapper接口使用。这种集成方式简化了持久层开发,使开发者能专注于业务逻辑。

m0_37607945的博客 438

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Mybatis核心机制与最佳实践解析

Mybatis作为Java生态中广泛使用的ORM框架,其核心原理基于SQL映射与参数处理机制。通过TypeHandler实现Java对象与数据库类型的转换,结合动态SQL标签实现灵活的查询构建。在工程实践中,合理使用#{}预处理参数能有效防止SQL注入,而批量操作与结果集映射优化可显著提升性能。本文以CRUD操作和动态SQL为切入点,深入解析Mybatis的参数绑定、缓存机制等核心功能,并分享在高并发场景下的防注入策略与性能调优经验。

weixin_30596735的博客 341

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

MyBatis Plus核心功能解析与企业级实践指南

MyBatis Plus作为MyBatis的增强工具,通过自动化CRUD操作和强大的条件构造器显著提升开发效率。其核心原理基于动态代理技术,自动生成Mapper实现类并智能推导SQL语句,支持Lambda表达式编写类型安全的查询条件。在分布式系统中,采用雪花算法解决ID生成冲突,通过多租户拦截器实现数据隔离。工程实践中,批量操作性能较传统方式提升5倍以上,结合Redis可实现高效二级缓存。该框架特别适合Spring Boot项目快速开发,能减少30%以上的持久层代码量,广泛应用于电商、金融等需要复杂查询和高

weixin_33843947的博客 388

MyBatis入门与实战:从JDBC痛点解析到核心机制深度应用

在Java企业级应用开发中,数据库持久化是核心环节。传统JDBC虽然提供了基础的数据库访问能力,但其冗长的样板代码、繁琐的资源管理和易错的手动映射,严重影响了开发效率与代码可维护性。为此,ORM(对象关系映射)框架应运而生,旨在通过自动化与配置化,将开发者从重复劳动中解放出来,使其更专注于业务逻辑与SQL优化。MyBatis作为一款“半自动化”的持久层框架,其核心价值在于平衡了控制权与开发效率。它不像Hibernate那样完全屏蔽SQL,而是将SQL的编写权交还给开发者,同时自动化处理JDBC底层的连接管理

weixin_34121282的博客 323
上一篇: Java 获取本机IP
下一篇: Spring Boot 使用dependencyManagement版本管理
嘿嘿不错
博客等级 码龄11年 10粉丝 128原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值