透彻掌握Spring整合MyBatis的原理彻底征服面试官,建议收藏

本文详细探讨了Spring如何整合MyBatis,包括SqlSessionFactory的创建过程,SqlSession的安全处理,以及Mapper接口的实现。重点讲解了SqlSessionFactoryBean、SqlSessionTemplate、SqlSessionDaoSupport、MapperScannerConfigurer和MapperFactoryBean的作用,阐述了Spring如何通过这些组件实现MyBatis的线程安全和简化使用。
摘要由CSDN通过智能技术生成

在MyBatis篇内容的最后我们来给大家详细介绍下Spring是如何整合MyBatis的。让大家彻底掌握MyBatis的底层设计原理及实现。
img

MyBatis整合Spring原理

把MyBatis集成到Spring里面,是为了进一步简化MyBatis的使用,所以只是对MyBatis做了一些封装,并没有替换MyBatis的核心对象。也就是说:MyBatis jar包中的SqlSessionFactory、SqlSession、MapperProxy这些类都会用到。mybatis-spring.jar里面的类只是做了一些包装或者桥梁的工作。

只要我们弄明白了这三个对象是怎么创建的,也就理解了Spring继承MyBatis的原理。我们把它分成三步:

  1. SqlSessionFactory在哪创建的。
  2. SqlSession在哪创建的。
  3. 代理类在哪创建的。

1 SqlSessionFactory

首先我们来看下在MyBatis整合Spring中SqlSessionFactory的创建过程,查看这步的入口在Spring的配置文件中配置整合的标签中

img

我们进入SqlSessionFactoryBean中查看源码发现,其实现了InitializingBean 、FactoryBean、ApplicationListener 三个接口

接口 方法 作用
FactoryBean getObject() 返回由FactoryBean创建的Bean实例
InitializingBean afterPropertiesSet() bean属性初始化完成后添加操作
ApplicationListener onApplicationEvent() 对应用的时间进行监听

1.1 afterPropertiesSet

我们首先来看下 afterPropertiesSet 方法中的逻辑

public void afterPropertiesSet() throws Exception {
 
    Assert.notNull(this.dataSource, "Property 'dataSource' is required");
    Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
    Assert.state(this.configuration == null && this.configLocation == null || this.configuration == null || this.configLocation == null, "Property 'configuration' and 'configLocation' can not specified with together");
    this.sqlSessionFactory = this.buildSqlSessionFactory();
}

可以发现在afterPropertiesSet中直接调用了buildSqlSessionFactory方法来实现 sqlSessionFactory 对象的创建

protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
 
        // 解析全局配置文件的 XMLConfigBuilder 对象
        XMLConfigBuilder xmlConfigBuilder = null;
        // Configuration 对象
        Configuration targetConfiguration;
        Optional var10000;
        if (this.configuration != null) {
  // 判断是否存在 configuration对象,如果存在说明已经解析过了
            targetConfiguration = this.configuration;
            // 覆盖属性
            if (targetConfiguration.getVariables() == null) {
 
                targetConfiguration.setVariables(this.configurationProperties);
            } else if (this.configurationProperties != null) {
 
                targetConfiguration.getVariables().putAll(this.configurationProperties);
            }
            // 如果configuration对象不存在,但是存在configLocation属性,就根据mybatis-config.xml的文件路径来构建 xmlConfigBuilder对象
        } else if (this.configLocation != null) {
   
            xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), (String)null, this.configurationProperties);
            targetConfiguration = xmlConfigBuilder.getConfiguration();
        } else {
 
            // 属性'configuration'或'configLocation'未指定,使用默认MyBatis配置
            LOGGER.debug(() -> {
 
                return "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration";
            });
            targetConfiguration = new Configuration();
            var10000 = Optional.ofNullable(this.configurationProperties);
            Objects.requireNonNull(targetConfiguration);
            var10000.ifPresent(targetConfiguration::setVariables);
        }
		// 设置 Configuration 中的属性  即我们可以在Mybatis和Spring的整合文件中来设置 MyBatis的全局配置文件中的设置
        var10000 = Optional.ofNullable(this.objectFactory);
        Objects.requireNonNull(targetConfiguration);
        var10000.ifPresent(targetConfiguration::setObjectFactory);
        var10000 = Optional.ofNullable(this.objectWrapperFactory);
        Objects.requireNonNull(targetConfiguration);
        var10000.ifPresent(targetConfiguration::setObjectWrapperFactory);
        var10000 = Optional.ofNullable(this.vfs);
        Objects.requireNonNull(targetConfiguration);
        var10000.ifPresent(targetConfiguration::setVfsImpl);
        Stream var24;
        if (StringUtils.hasLength(this.typeAliasesPackage)) {
 
            var24 = this.scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream().filter((clazz) -> {
 
                return !clazz.isAnonymousClass();
            }).filter((clazz) -> {
 
                return !clazz.isInterface();
            }).filter((clazz) -> {
 
                return !clazz.isMemberClass();
            });
            TypeAliasRegi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值