你今天微笑了吗?嘿嘿
最近遇到一个问题:在一个基于maven构建的使用springboot和Mybatis-Plus整合的一个多组件项目,其中在组件A中application.yml文件中配置了Mybatis-Plus配置项mapper-locations如下:
mybatis-plus: mapper-locations: classpath:mapper/**/*.xml
项目中组件依赖关系是:组件A依赖组件B和C,组件B和C中都有满足上述配置项的mapper xml文件,但是发现启动组件A后只加载了组件B和C其一下的mapper文件(具体加载哪个是以在组件A的pom文件中配置的对组件B、C的dependency的先后顺序为准,先配置的被加载),未被加载的在使用的时候会报错:org.apache.ibatis.binding.BindingException:Invalid bound statement (not found)。 在网上找了解决办法:把classpath改成classpath*,改后试了一下确实OK了,然后又找几篇文章看了一下spring在加载classpath和classpath*路径下的文件有什么区别,几篇文章只讲了结论,有的说法还不一,看完感觉只知其然而不知其所以然,所以决定自己看源码学习一下,也简单总结了一下,分享给有同样需求的小伙伴
先从项目Mybatis-Plus该配置项入手,我们知道springboot的yml配置文件中的每项配置都有其对应的属性文件,找到Mybatis-plus相关属性配置文件如下:这里只复制了和配置项相关的代码
MybatisPlusProperties.java:@ConfigurationProperties(prefix = "mybatis-plus")public class MybatisPlusProperties {
private static final ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); ...... public Resource[] resolveMapperLocations() {
return Stream.of(Optional.ofNullable(this.mapperLocations).orElse(new String[0])) .flatMap(location -> Stream.of(getResources(location))) .toArray(Resource[]::new); } private Resource[] getResources(String location) {
try {
return resourceResolver.getResources(location); } catch (IOException e) {
return new Resource[0]; } } }
我们看到实质加载资源文件就是通过PathMatchingResourcePatternResolver类的getResources方法加载的,PathMatchingResourcePatternResolver类是spring-core模块的一个类,所以我们这里单独搭建一个spring项目测试一下看一下源码,项目工程结构如下: