理解 MyBatis 是如何在 Spring 容器中初始化的
MyBatis初始化过程就是生成一些必须的对象放到Spring容器中。问题是这个过程到底生成了哪些对象?当遇到MyBatis初始化失败时,如何正确的找到分析问题的切入点?本文将针对这些问题进行介绍。
本文基于MyBatis3和Spring,假设读者已经知道如何使用Maven和MyBatis,以及了解Spring的容器机制。
一、Mybatis三件套
我们知道MyBatis的主要功能是由SqlSessionFactory和Mapper两者提供的,初始化MyBatis就是初始化这两类对象。除此之外DataSource作为数据库访问对象也是必不可少。因此首先我们应该记住MyBatis初始化的核心三件套:
- DataSource:它是访问数据库所必须的数据源对象,这个初始化失败就无法直接访问数据库。
- SqlSessionFactoryBean:这是在Spring容器中对SqlSessionFactory初始化过程的封装。
- MapperScannerConfigurer:这是在Spring容器中对Mapper初始化过程的封装。
具体来说,一个简单的初始化过程就是下面这样:
@Configuration publicclassSpringMyBatisApplication{ publicstaticvoidmain(String[]args){ newAnnotationConfigApplicationContext(SpringMyBatisApplication.class); } @Bean publicDataSourcedataSource(){ return...; } @Bean publicSqlSessionFactoryBeansqlSessionFactoryBean(DataSourcedataSource){ return...; } @Bean publicMapperScannerConfigurermapperScannerConfigurer(){ return...; } }
接下来介绍三件套各自如何初始化,下面的内容是可以实际操作的,不妨动手试试。
1.DataSource初始化
首先我们创建一个空的Maven项目,在pom.xml中加入下面的依赖关系:
org.springframework spring-beans 5.2.0.RELEASE org.springframework spring-context-support 5.2.0.RELEASE org.springframework spring-jdbc 5.2.0.RELEASE org.springframework spring-tx 5.2.0.RELEASE org.apache.commons commons-dbcp2 2.7.0 com.h2database h2 1.4.199
本文重在演示MyBatis的初始化过程,所以没有复杂的SQL,数据库用的是嵌入式数据库h2。
然后我们在com.hyd.mybatis3test包下面创建一个SpringMyBatisApplication类,代码在前面给过了。
对应的DataSource初始化实现如下:
@Bean publicDataSourcedataSource(){ BasicDataSourcedataSource=newBasicDataSource(); dataSource.setDriverClassName("org.h2.Driver"); dataSource.setUrl("jdbc:h2:mem:test"); returndataSource; }
2.SqlSessionFactoryBean初始化
SqlSessionFactoryBean是对SqlSessionFactory初始化过程的封装,Spring会在适当的时候执行这个初始化过程,得到最终的SqlSessionFactory对象。
SqlSessionFactoryBean的创建过程如下(注意方法签名在前面的基础上有变动):
@Bean publicSqlSessionFactoryBeansqlSessionFactory( DataSourcedataSource, ResourcePatternResolverresolver )throwsException{ SqlSessionFactoryBeanbean=newSqlSessionFactoryBean(); bean.setDataSource(dataSource); bean.setMapperLocations(resolver.getResources("classpath*:mappers/*.xml")); returnbean; }
其中:
- 第一个参数dataSource就是前面生成的数据源对象;
- 第二个参数resolver是Spring自动提供的,用于搜索指定路径下的所有xml文件。本文不会包含xml文件,所以这个配置是无效的,这行可以不写,不过写了也不影响程序运行。
3.MapperScannerConfigurer初始化
MapperScannerConfigurer的职责是在指定路径下搜索所有的Mapper接口类(参考它的postProcessBeanDefinitionRegistry()方法),并通过MapperFactoryBean将其注册到MapperRegistry中。
@Bean publicMapperScannerConfigurermapperScannerConfigurer(){ MapperScannerConfigurerconfigurer=newMapperScannerConfigurer(); configurer.setBasePackage("com.hyd.mybatis3test"); returnconfigurer; }
4.验证初始化过程成功
为了验证上面的初始化过程完成了,我们在com.hyd.mybatis3test包下面创建一个Mapper类:
@Mapper publicinterfaceSampleMapper{ @Update("createtableifnotexistsuser(idint)") voidcreateUserTable(); }
以及一个Service类:
@Service publicstaticclassSampleService{ @Autowired privateSampleMappersampleMapper; @PostConstruct publicvoidinit(){ sampleMapper.createUserTable(); } }
然后别忘了在SpringMyBatisApplication顶上添加一个@ComponentScan("com.hyd.mybatis3test")注解,否则Spring会找不到SampleService。
运行SpringMyBatisApplication.main()方法,我们就能在输出中找到这样的内容:
...
SampleMapper.createUserTable-==> Preparing:createtableifnotexistsuser(idint)
SampleMapper.createUserTable-==>Parameters:
SampleMapper.createUserTable-<== Updates:0
...
这说明这条创建表格的SQL语句成功执行了。
在前面三件套的基础上,MyBatis也提供了更多的封装。有了本文上面的铺垫,相信读者对这些封装方式理解起来也会轻松很多。
二、@MapperScan注解
@MapperScan注解只不过是MapperScannerConfigurer的启动器而已,使用这个注解,可以代替前面的MapperScannerConfigurer初始化。
三、SpringBoot自动初始化
MyBatis提供mybatis-spring-boot-starter库用于在SpringBoot项目中自动初始化:
org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.3
这个所谓的自动初始化实际上就是初始化SqlSessionFactory对象。初始化的过程由org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration完成,所需的配置都从"mybatis-"前缀的配置属性中获取,具体可以参考org.mybatis.spring.boot.autoconfigure.MybatisProperties类。
总结
总之,MyBatis的初始化核心过程就是三件套的初始化。而在SpringBoot应用中,结合自动初始化和@MapperScan注解,我们无需手工初始化上这三件套,就能直接从容器中得到Mapper对象。
到此这篇关于理解MyBatis是如何在Spring容器中初始化的的文章就介绍到这了,更多相关mybatis在spring中的初始化内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!