MyBatis-Plus配置未生效的问题及解决

 更新时间:2025年12月18日 10:38:14   作者:李少兄  
本文主要探讨了在使用MyBatis-Plus进行数据库操作时遇到的问题,包括SQL语句未生效、Mapper接口未扫描、属性未注入、Bean未注册等问题,通过分析SpringBoot的配置类加载机制,本文提出了两种解决方案:添加@Configuration注解和使用AutoConfiguration.imports文件

一、问题背景

在使用 MyBatis-Plus 进行数据库操作时,遇到以下问题:

  • SQL 语句未生效:分页、乐观锁、数据权限等插件未起作用。
  • Mapper 接口未扫描@MapperScan 未正确加载 Mapper 类,@MapperScan指定的Mapper包未被扫描,导致No mapper was found错误。
  • 属性未注入@PropertySource 中的配置文件未被解析。
  • Bean未注册:通过@Bean声明的Bean未在Spring容器中注册,导致依赖注入失败。

这个原因可能就是写的配置类没生效,下面详细讲讲

二、问题根源分析

1. Spring Boot 的配置类加载机制

(1)组件扫描(Component Scanning)

触发条件:默认由@SpringBootApplication注解(包含@ComponentScan)触发。

扫描范围:默认扫描主启动类的同包及子包。

识别规则

  • 扫描到带有@Configuration的类,注册其@Bean方法。
  • 扫描到@Component@Service@Repository等注解的类,注册为Bean。

(2)显式声明(Explicit Declaration)

  • @Import注解:在配置类中直接导入其他配置类。
  • spring.factories文件:Spring Boot 2.6及以下版本的核心自动配置文件。
  • AutoConfiguration.imports文件:Spring Boot 2.7+引入的轻量级替代方案。

(3)类路径扫描

Spring Boot启动时,会扫描META-INF/spring.factoriesMETA-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,加载声明的配置类。

2. 问题产生的关键原因

(1) 缺少@Configuration注解

问题:配置类未被 Spring 识别为配置类,导致其 @Bean 方法未被注册。

示例

// 错误示例:缺少 @Configuration
@EnableTransactionManagement
@MapperScan("com.example.mapper")
public class MyBatisConfig {
    @Bean
    public MybatisPlusInterceptor interceptor() { ... }
}

(2) 配置类未被自动加载

  • 问题:配置类不在组件扫描路径,且未通过 AutoConfiguration.imports 声明。
  • 场景:多模块项目中,配置类位于独立模块或第三方 JAR 包中。
  • 关键点:Spring Boot优先加载AutoConfiguration.imports中声明的类,无需依赖扫描路径。

(3) 未被组件扫描覆盖

问题:配置类位于主启动类的非扫描路径下,导致Spring无法发现该类。

示例

// 主启动类位于com.example包
@SpringBootApplication
public class Application {}

// 配置类位于com.example.config子包 → 可被扫描
@Configuration
public class MyConfig {}

// 配置类位于com.other包 → 无法被扫描
@Configuration
public class MyOtherConfig {}

三、解决方案一:添加@Configuration注解

1. 解决思路

通过 @Configuration 注解标记配置类,使 Spring Boot 能识别并加载其 @Bean 方法。

2. 核心原理

@Configuration注解

  • 标记该类为配置类,Spring会将其@Bean方法转换为Bean定义。
  • 触发Spring的CGLIB代理,生成配置类的代理对象。

组件扫描机制

  • 配置类需位于Spring的组件扫描路径下,或通过@ComponentScan显式指定路径。

3. 实现步骤

(1) 添加注解

@Configuration // 标记为配置类
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan("${mybatis-plus.mapperPackage}")
@PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class)
public class MyBatisConfig {
    // 配置拦截器、数据源等
}

(2) 确保组件扫描路径

方式1:配置类位于主启动类的同包或子包中。

方式2:显式指定扫描路径:

@SpringBootApplication
@ComponentScan(basePackages = {"com.example.config"}) // 包含配置类的包路径
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

4. 规范与注意事项

  • 必须添加@Configuration 是配置类生效的必要条件。
  • 组件扫描范围:若配置类在独立模块或第三方库中,需通过 @ComponentScanAutoConfiguration.imports 显式加载。

四、解决方案二:使用AutoConfiguration.imports文件

1. 解决思路

通过 AutoConfiguration.imports 文件,强制 Spring Boot 加载指定的配置类,无需依赖组件扫描

2. 核心原理

AutoConfiguration.imports文件

  • 作用:直接声明需要加载的配置类,无需依赖组件扫描路径。
  • 优先级:Spring Boot 3.0+中优先于spring.factories文件。
  • 实现机制:通过AutoConfigurationImportSelector解析文件内容,生成Bean定义。

3. 实现步骤

(1) 创建文件

在项目资源目录下创建路径:

src/main/resources/
└── META-INF/
    └── spring/
        └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

(2) 填写内容

文件内容为配置类的全限定名,每行一个:

# 示例:加载 MyBatis 配置类
com.example.config.MyBatisConfig

# 其他配置类(可选)
com.example.config.OtherConfig

(3) 验证文件路径

确保文件路径正确,且无拼写错误(如 META-INF/spring 而非 META-INF/spring.factories)。

4. 规范与注意事项

  • 文件路径:必须位于 META-INF/spring 目录下。
  • 类名格式:必须使用全限定名(包名+类名)。
  • 版本要求:Spring Boot 2.7+ 支持此功能,旧版本需使用 spring.factories

五、两种方案的对比与选择

方案适用场景优势限制
@Configuration单模块项目,配置类位于主包路径下简单直接,无需额外文件依赖组件扫描路径,多模块时可能冲突
AutoConfiguration.imports多模块项目、第三方库、配置类需独立加载解耦模块,无需修改组件扫描路径需手动创建文件,文件路径需严格符合规范

1. 组合使用场景

在复杂项目中,可结合两者:

@Configuration // 标记配置类
public class MyBatisConfig { ... }

同时在 AutoConfiguration.imports 中声明:

com.example.config.MyBatisConfig

六、原理深入:Spring Boot 的自动配置机制

1. 自动配置流程

启动阶段:Spring Boot 会扫描以下资源:

  • META-INF/spring.factories:传统自动配置文件。
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:新机制。

加载配置类:根据 AutoConfiguration.imports 中的类名,加载对应的配置类。

注册 Bean:解析 @Configuration 类中的 @Bean 方法,注册到 Spring 容器。

2.AutoConfiguration.imports的底层实现

  • 优先级:比 spring.factories 更高效,仅加载声明的类。
  • 机制:通过 SpringFactoriesLoader 加载文件中的类,并调用 @Configuration@Bean 方法。

七、常见问题

1. 最佳实践

(1) 多模块项目配置

  • 主模块:在 AutoConfiguration.imports 中声明所有公共配置类。
  • 子模块:通过 @Configuration 标记本地配置类,或在父模块中统一声明。

步骤

在父POM中统一管理依赖:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>
    </dependencies>
</dependencyManagement>

在配置模块中创建AutoConfiguration.imports,声明配置类:

com.parentmodule.config.MybatisPlusConfig

2. 结合条件注解的动态配置

通过@ConditionalOnProperty实现条件化加载:

@Configuration
@ConditionalOnProperty(prefix = "mybatis-plus", name = "enabled", havingValue = "true")
public class MybatisPlusConfig {
    // 配置内容
}

(2) 第三方库集成

  • JAR 包提供者:在 JAR 的 META-INF/spring 目录中提供 AutoConfiguration.imports
  • 用户端:无需额外配置,直接引入依赖即可生效。

2. 常见问题与解决

(1) 配置类未生效

  • 原因:缺少 @Configuration 或文件路径错误。
  • 解决:检查注解和文件路径,确保类名与包路径一致。

(2) 文件路径错误

  • 症状:日志未输出配置类加载信息。
  • 解决:确保路径为 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

(3) 类名拼写错误

  • 症状:启动时抛出 ClassNotFoundException
  • 解决:检查文件中的类名是否与实际包路径完全匹配。

3. 验证配置是否生效

方法1:日志检查

启动日志应包含以下信息:

Loading configuration class 'com.yourpackage.config.MybatisPlusConfig'

方法2:测试Bean注册

在任意@Service@Component中注入配置的Bean:

@Autowired
private MybatisPlusInterceptor interceptor;

@PostConstruct
public void init() {
    System.out.println("Interceptor: " + interceptor);
}

八、完整示例代码

1. 配置类(MyBatisConfig.java)

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@MapperScan("${mybatis-plus.mapperPackage}")
@PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class)
public class MyBatisConfig {

    @Bean
    public MybatisPlusInterceptor interceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return interceptor;
    }
}

2. AutoConfiguration.imports 文件

# src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.config.MyBatisConfig

3. 启动类(Application.java)

@SpringBootApplication
@ComponentScan(basePackages = {"com.example"}) // 可选:显式指定扫描路径
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

九、总结

@Configuration 是配置类生效的基础,必须添加。

AutoConfiguration.imports 是加载配置类的机制,适用于复杂项目。

组合使用两者 可以平衡灵活性与解耦性,适应不同场景。

  • 方案一:适合单模块、路径简单的项目。
  • 方案二:适合多模块、复杂路径或第三方库的自动配置。
维度@ConfigurationAutoConfiguration.imports
加载机制依赖组件扫描路径无需扫描,直接声明加载
适用场景单模块、路径简单多模块、第三方JAR、复杂路径
性能可能受组件扫描路径影响更高效,仅加载声明的类
依赖关系需确保依赖的Bean已注册需确保依赖的Bean已通过其他方式注册
代码侵入性需修改配置类代码无需修改代码,仅需文件声明

选择建议

  • 优先方案一:若配置类位于主包路径,且项目结构简单。
  • 优先方案二:若项目为多模块或需避免组件扫描范围冲突。

Spring Boot版本兼容性

  • Spring Boot 2.6及以下:仅支持spring.factories
  • Spring Boot 2.7+:支持AutoConfiguration.imports,但兼容spring.factories
  • Spring Boot 3.0+:完全弃用spring.factories的自动配置功能。

扩展阅读

通过本文的详细讲解,相信读者已能深刻理解配置未生效的原因,并能灵活运用两种解决方案。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java Lombok实现手机号码校验的示例代码

    Java Lombok实现手机号码校验的示例代码

    手机号码校验通常是系统开发中最基础的功能之一,本文主要介绍了Java Lombok实现手机号码校验的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • jmeter添加自定函数的实例(jmeter5.3+IntelliJ IDEA)

    jmeter添加自定函数的实例(jmeter5.3+IntelliJ IDEA)

    这篇文章主要介绍了jmeter添加自定函数的实例(jmeter5.3+IntelliJ IDEA),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Java使用Spring Batch处理大规模数据的实践分享

    Java使用Spring Batch处理大规模数据的实践分享

    在处理大规模数据的场景中,批处理是一个非常常见且必要的操作,Java中的Spring Batch是一个强大的框架,能够帮助我们高效地执行复杂的批处理任务,本文将带大家了解如何使用Spring Batch处理大规模数据,并通过代码示例展示如何实现高效的批处理,需要的朋友可以参考下
    2024-10-10
  • springboot+vue实现阿里云oss大文件分片上传的示例代码

    springboot+vue实现阿里云oss大文件分片上传的示例代码

    阿里云推出了直传,本文主要介绍了springboot+vue实现阿里云oss大文件分片上传的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • Java程序员面试中的多线程问题总结

    Java程序员面试中的多线程问题总结

    这篇文章收集了 Java 线程方面一些典型的问题,这些问题经常被高级工程师所问到。这篇文章收集了 Java 线程方面一些典型的问题,这些问题经常被高级工程师所问到。
    2016-11-11
  • java占位符替换五种方式小结

    java占位符替换五种方式小结

    我们经常会遇到需要替换字符串中的占位符的情况,本文主要介绍了java占位符替换五种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-06-06
  • 利用Java多线程技术导入数据到Elasticsearch的方法步骤

    利用Java多线程技术导入数据到Elasticsearch的方法步骤

    这篇文章主要介绍了利用Java多线程技术导入数据到Elasticsearch的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-07-07
  • SpringBoot设置静态资源访问控制和封装集成方案

    SpringBoot设置静态资源访问控制和封装集成方案

    这篇文章主要介绍了SpringBoot静态资源访问控制和封装集成方案,关于springboot静态资源访问的问题,小编是通过自定义webconfig实现WebMvcConfigurer,重写addResourceHandlers方法,具体完整代码跟随小编一起看看吧
    2021-08-08
  • JDBC连接mysql乱码异常问题处理总结

    JDBC连接mysql乱码异常问题处理总结

    这篇文章主要介绍了JDBC连接mysql乱码异常问题处理的办法和思路,有需要的朋友参考学习下。
    2017-12-12
  • Java出现:JWT strings must contain exactly 2 period characters. Found: 0的常见原因及解决方案

    Java出现:JWT strings must contain exactly&

    这篇文章主要介绍了JWT令牌解析失败的原因和解决方法,包括Header、Payload和Signature三段式结构,常见错误原因,通用解决方案以及额外注意点,需要的朋友可以参考下
    2026-01-01

最新评论