You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring AOT处理阶段如何正常读取MybatisProperties配置

Spring AOT处理时无法读取MybatisProperties的mapperLocations配置

问题描述

在Spring AOT编译处理阶段,自定义的MybatisBeanFactoryInitializationAotContribution中注入MybatisProperties后,调用getMapperLocations()返回空值,无法获取application.yml中配置的mybatis.mapper-locations值,导致无法正确注册资源RuntimeHints。

相关代码与配置如下:

自定义AOT贡献类

public class MybatisBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution {

    private final MybatisProperties mybatisProperties;

    public MybatisBeanFactoryInitializationAotContribution(MybatisProperties mybatisProperties) {
        this.mybatisProperties = mybatisProperties;
    }

    @Override
    public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) {
        log.info("MybatisBeanFactoryInitializationAotContribution {}", mybatisProperties.getMapperLocations());

        RuntimeHints hints = generationContext.getRuntimeHints();

        String[] mapperLocations = mybatisProperties.getMapperLocations();
        if (mapperLocations != null) {
            log.info("mapperLocations-{}", mapperLocations);
            Stream.of(mapperLocations).map(item -> item.replace("classpath:/", "")).forEach(hints.resources()::registerPattern);
        }
    }

}

application.yml配置

mybatis:
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:/mapper/*.xml

原因分析

Spring AOT是编译期预处理机制,此时常规的@ConfigurationProperties自动绑定流程尚未完全执行。直接注入的MybatisProperties实例是通过默认构造函数创建的,并未完成与application.yml配置的绑定,因此所有属性都是默认值(比如mapperLocations默认返回null)。

解决方案

方案1:通过Environment手动绑定属性

绕过自动绑定的时机限制,直接从Environment中读取配置并手动绑定到MybatisProperties实例:

修改后的MybatisBeanFactoryInitializationAotContribution:

import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.core.env.Environment;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import java.util.Arrays;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MybatisBeanFactoryInitializationAotContribution implements BeanFactoryInitializationAotContribution {

    private static final Logger log = LoggerFactory.getLogger(MybatisBeanFactoryInitializationAotContribution.class);

    @Override
    public void applyTo(GenerationContext generationContext, BeanFactoryInitializationCode beanFactoryInitializationCode) {
        // 从BeanFactory获取Environment
        ConfigurableListableBeanFactory beanFactory = generationContext.getBeanFactory();
        Environment environment = beanFactory.getEnvironment();

        // 手动绑定MybatisProperties
        MybatisProperties mybatisProperties = Binder.get(environment)
                .bind("mybatis", MybatisProperties.class)
                .orElse(new MybatisProperties());

        log.info("MybatisBeanFactoryInitializationAotContribution mapperLocations: {}", Arrays.toString(mybatisProperties.getMapperLocations()));

        RuntimeHints hints = generationContext.getRuntimeHints();
        String[] mapperLocations = mybatisProperties.getMapperLocations();
        if (mapperLocations != null) {
            Stream.of(mapperLocations)
                    .map(location -> location.replace("classpath:/", ""))
                    .forEach(hints.resources()::registerPattern);
        }
    }
}

方案2:确保MybatisProperties提前完成初始化

在注册AOT贡献类时,先从BeanFactory中获取并初始化MybatisProperties,触发属性绑定:

对应的AOT处理器类:

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotProcessor;
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;

public class MybatisBeanFactoryInitializationAotProcessor implements BeanFactoryInitializationAotProcessor {

    @Override
    public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
        // 主动获取MybatisBean,触发属性绑定
        MybatisProperties mybatisProperties = beanFactory.getBean(MybatisProperties.class);
        return new MybatisBeanFactoryInitializationAotContribution(mybatisProperties);
    }
}

注意事项

  • 确保application.yml等配置文件位于src/main/resources目录下,编译时能被正确加载到classpath中。
  • 若使用多环境配置,需在AOT编译时指定激活的环境(如通过-Dspring.profiles.active=dev参数),确保读取到正确的配置。

内容的提问来源于stack exchange,提问作者Qeir Mr.钟

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:34:54