springboot项目的配置文件中有如下配置:
#mybatis指向
mybatis:
mapper-locations: classpath:mapping/*.xml
#type-aliases-package: com.demo3.demo.entity
configuration:
map-underscore-to-camel-case: true
配置了mapper资源的路径,那么具体的mapper资源是如何别加载到运行时的呢?
项目启动时,会加载这个类:
MybatisAutoConfiguration
这个类内部使用了另一个类:
MybatisProperties
运行时就是通过这两个类的处理,还获取mapper.xml这种物理资源的。
MybatisAutoConfiguration中是在生成一个sql会话工厂(SqlSessionFactory)的时候用到了MybatisProperties。
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
...
...
// resolveMapperLocations()方法获取mapper资源
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
factory.setMapperLocations(this.properties.resolveMapperLocations());
}
return factory.getObject();
}
以上代码有这句:
this.properties.resolveMapperLocations()
resolveMapperLocations()方法中具体逻辑:
public Resource[] resolveMapperLocations() {
ResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
List<Resource> resources = new ArrayList();
if (this.mapperLocations != null) {
String[] var3 = this.mapperLocations;
int var4 = var3.length;
for(int var5 = 0; var5 < var4; ++var5) {
String mapperLocation = var3[var5];
try {
// mapperLocation的值:classpath:mapping/*.xml
// getResources获取mapper.xml资源信息
Resource[] mappers = resourceResolver.getResources(mapperLocation);
resources.addAll(Arrays.asList(mappers));
} catch (IOException var8) {
}
}
}
return (Resource[])resources.toArray(new Resource[resources.size()]);
}
方法getResources()的具体逻辑:
public Resource[] getResources(String locationPattern) throws IOException {
Assert.notNull(locationPattern, "Location pattern must not be null");
if (locationPattern.startsWith("classpath*:")) {
return this.getPathMatcher().isPattern(locationPattern.substring("classpath*:".length())) ? this.findPathMatchingResources(locationPattern) : this.findAllClassPathResources(locationPattern.substring("classpath*:".length()));
} else {
int prefixEnd = locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 : locationPattern.indexOf(58) + 1;
// findPathMatchingResources方法获取mapper.xml资源
return this.getPathMatcher().isPattern(locationPattern.substring(prefixEnd)) ? this.findPathMatchingResources(locationPattern) : new Resource[]{this.getResourceLoader().getResource(locationPattern)};
}
}
findPathMatchingResources方法具体逻辑:
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
String rootDirPath = this.determineRootDir(locationPattern);
String subPattern = locationPattern.substring(rootDirPath.length());
// rootDirResources的path: "mapping/"
Resource[] rootDirResources = this.getResources(rootDirPath);
Set<Resource> result = new LinkedHashSet(16);
Resource[] var6 = rootDirResources;
int var7 = rootDirResources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Resource rootDirResource = var6[var8];
Resource rootDirResource = this.resolveRootDirResource(rootDirResource);
// mapping文件夹物理路径
URL rootDirUrl = ((Resource)rootDirResource).getURL();
if (equinoxResolveMethod != null && rootDirUrl.getProtocol().startsWith("bundle")) {
URL resolvedUrl = (URL)ReflectionUtils.invokeMethod(equinoxResolveMethod, (Object)null, new Object[]{rootDirUrl});
if (resolvedUrl != null) {
rootDirUrl = resolvedUrl;
}
rootDirResource = new UrlResource(rootDirUrl);
}
if (rootDirUrl.getProtocol().startsWith("vfs")) {
result.addAll(PathMatchingResourcePatternResolver.VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, this.getPathMatcher()));
} else if (!ResourceUtils.isJarURL(rootDirUrl) && !this.isJarResource((Resource)rootDirResource)) {
// doFindPathMatchingFileResources方法来加载mapper资源
result.addAll(this.doFindPathMatchingFileResources((Resource)rootDirResource, subPattern));
} else {
result.addAll(this.doFindPathMatchingJarResources((Resource)rootDirResource, rootDirUrl, subPattern));
}
}
if (logger.isTraceEnabled()) {
logger.trace("Resolved location pattern [" + locationPattern + "] to resources " + result);
}
return (Resource[])result.toArray(new Resource[0]);
}
doFindPathMatchingJarResources()
protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern) throws IOException {
File rootDir;
try {
// 此处将会获取到具体的mapper文件
rootDir = rootDirResource.getFile().getAbsoluteFile();
} catch (FileNotFoundException var5) {
if (logger.isDebugEnabled()) {
logger.debug("Cannot search for matching files underneath " + rootDirResource + " in the file system: " + var5.getMessage());
}
return Collections.emptySet();
} catch (Exception var6) {
if (logger.isInfoEnabled()) {
logger.info("Failed to resolve " + rootDirResource + " in the file system: " + var6);
}
return Collections.emptySet();
}
return this.doFindMatchingFileSystemResources(rootDir, subPattern);
}
获取到具体的mapper.xml资源后,运行时会将此放到sqlSessionFactory中,供后续使用。