Spring 对MyBatis 的对象进行了管理,但是并不会替换MyBatis 的核心对象。也就意味着:MyBatis jar 包中的SqlSessionFactory、SqlSession、MapperProxy 这些都会用到。而mybatis-spring.jar 里面的类只是做了一些包装或者桥梁的工作。
所以第一步,我们看一下在Spring 里面,工厂类是怎么创建的。
我们在Spring 的配置文件中配置了一个SqlSessionFactoryBean,我们来看一下这个类。
它实现了InitializingBean 接口,所以要实现afterPropertiesSet()方法,这个方法会在bean 的属性值设置完的时候被调用。
另外它实现了FactoryBean 接口,所以它初始化的时候,实际上是调用getObject()方法,它里面调用的也是afterPropertiesSet()方法。
在afterPropertiesSet()方法里面:
第一步是一些标签属性的检查,接下来调用了buildSqlSessionFactory()方法。
然后定义了一个Configuration,叫做targetConfiguration。
426 行,判断Configuration 对象是否已经存在,也就是是否已经解析过。如果已经有对象,就覆盖一下属性。
433 行,如果Configuration 不存在,但是配置了configLocation 属性,就根据mybatis-config.xml 的文件路径,构建一个xmlConfigBuilder 对象。
436 行,否则,Configuration 对象不存在,configLocation 路径也没有,只能使用默认属性去构建去给configurationProperties 赋值。
后面就是基于当前factory 对象里面已有的属性,对targetConfiguration 对象里面属性的赋值。
Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
这个方法是Java8 里面的一个判空的方法。如果不为空的话,就会调用括号里面的对象的方法,做赋值的处理。
在第498 行,如果xmlConfigBuilder 不为空,也就是上面的第二种情况,调用了xmlConfigBuilder.parse()去解析配置文件,最终会返回解析好的Configuration 对象。
在第507 行, 如果没有明确指定事务工厂, 默认使用SpringManagedTransactionFactory 。它创建的SpringManagedTransaction 也有getConnection()和close()方法。
<property name="transactionFactory" value="" />
在520 行,调用xmlMapperBuilder.parse(),这个步骤我们之前了解过了,它的作用是把接口和对应的MapperProxyFactory 注册到MapperRegistry 中。
最后调用sqlSessionFactoryBuilder.build() 返回了一个DefaultSqlSessionFactory。
OK,在这里我们完成了编程式的案例里面的第一步,根据配置文件获得一个工厂类,它是单例的,会在后面用来创建SqlSession。
用到的Spring 扩展点总结:
接口 | 方法 | 作用 |
FactoryBean | getObject() | 返回由FactoryBean 创建的Bean 实例 |
InitializingBean | afterPropertiesSet() | bean 属性初始化完成后添加操作 |
BeanDefinitionRegistryPostProcessor | postProcessBeanDefinitionRegistry() | 注入BeanDefination 时添加操作 |