mybatis的配置是如何被springtboot项目加载的

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中,供后续使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值