关于java:理解-MyBatis-是如何在-Spring-容器中初始化的

21次阅读

共计 4323 个字符,预计需要花费 11 分钟才能阅读完成。

MyBatis 初始化过程就是 生成一些必须的对象放到 Spring 容器中。问题是这个过程到底生成了哪些对象?当遇到 MyBatis 初始化失败时,如何正确的找到剖析问题的切入点?本文将针对这些问题进行介绍。

本文基于 MyBatis 3 和 Spring,假如读者曾经晓得如何应用 Maven 和 MyBatis,以及理解 Spring 的容器机制。

一、Mybatis 三件套

咱们晓得 MyBatis 的次要性能是由 SqlSessionFactory 和 Mapper 两者提供的,初始化 MyBatis 就是初始化这两类对象。除此之外 DataSource 作为数据库拜访对象也是必不可少。因而首先咱们应该记住 MyBatis 初始化的外围三件套:

  • DataSource:它是拜访数据库所必须的数据源对象,这个初始化失败就无奈间接拜访数据库。
  • SqlSessionFactoryBean:这是在 Spring 容器中对 SqlSessionFactory 初始化过程的封装。
  • MapperScannerConfigurer:这是在 Spring 容器中对 Mapper 初始化过程的封装。

具体来说,一个简略的初始化过程就是上面这样:

@Configuration
public class SpringMyBatisApplication {public static void main(String[] args) {new AnnotationConfigApplicationContext(SpringMyBatisApplication.class);
    }
    @Bean
    public DataSource dataSource() {return ...;}
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {return ...;}
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {return ...;}
}

接下来介绍三件套各自如何初始化,上面的内容是能够实际操作的,无妨入手试试。

1. DataSource 初始化

首先咱们创立一个空的 Maven 我的项目,在 pom.xml 中退出上面的依赖关系:

<!-- Spring -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-beans</artifactId>
  <version>5.2.0.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context-support</artifactId>
  <version>5.2.0.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>5.2.0.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-tx</artifactId>
  <version>5.2.0.RELEASE</version>
</dependency>

<!-- 数据库 -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-dbcp2</artifactId>
  <version>2.7.0</version>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <version>1.4.199</version>
</dependency>

本文重在演示 MyBatis 的初始化过程,所以没有简单的 SQL,数据库用的是嵌入式数据库 h2。

而后咱们在 com.hyd.mybatis3test 包上面创立一个 SpringMyBatisApplication 类,代码在后面给过了。

对应的 DataSource 初始化实现如下:

@Bean
public DataSource dataSource() {BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("org.h2.Driver");
    dataSource.setUrl("jdbc:h2:mem:test");
    return dataSource;
}

2. SqlSessionFactoryBean 初始化

SqlSessionFactoryBean 是对 SqlSessionFactory 初始化过程的封装,Spring 会 在适当的时候 执行这个初始化过程,失去最终的 SqlSessionFactory 对象。

SqlSessionFactoryBean 的创立过程如下(留神办法签名在后面的根底上有变动):

@Bean
public SqlSessionFactoryBean sqlSessionFactory(
        DataSource dataSource,
        ResourcePatternResolver resolver
) throws Exception {SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setMapperLocations(resolver.getResources("classpath*:mappers/*.xml"));
    return bean;
}

其中:

  • 第一个参数 dataSource 就是后面生成的数据源对象;
  • 第二个参数 resolver 是 Spring 主动提供的,用于搜寻指定门路下的所有 xml 文件。本文不会蕴含 xml 文件,所以这个配置是有效的,这行能够不写,不过写了也不影响程序运行。

3. MapperScannerConfigurer 初始化

MapperScannerConfigurer 的职责是在指定门路下搜寻所有的 Mapper 接口类(参考它的 postProcessBeanDefinitionRegistry() 办法),并通过 MapperFactoryBean 将其注册到 MapperRegistry 中。

@Bean
public MapperScannerConfigurer mapperScannerConfigurer() {MapperScannerConfigurer configurer = new MapperScannerConfigurer();
    configurer.setBasePackage("com.hyd.mybatis3test");
    return configurer;
}

4. 验证初始化过程胜利

为了验证下面的初始化过程实现了,咱们在 com.hyd.mybatis3test 包上面创立一个 Mapper 类:

@Mapper
public interface SampleMapper {@Update("create table if not exists user(id int)")
    void createUserTable();}

以及一个 Service 类:

@Service
public static class SampleService {
    @Autowired
    private SampleMapper sampleMapper;
    @PostConstruct
    public void init() {sampleMapper.createUserTable();
    }
}

而后别忘了在 SpringMyBatisApplication 顶上增加一个 @ComponentScan("com.hyd.mybatis3test") 注解,否则 Spring 会找不到 SampleService。

运行 SpringMyBatisApplication.main() 办法,咱们就能在输入中找到这样的内容:

...
SampleMapper.createUserTable - ==>  Preparing: create table if not exists user(id int)
SampleMapper.createUserTable - ==> Parameters:
SampleMapper.createUserTable - <==    Updates: 0
...

这阐明这条创建表格的 SQL 语句胜利执行了。

在后面三件套的根底上,MyBatis 也提供了更多的封装。有了本文下面的铺垫,置信读者对这些封装形式了解起来也会轻松很多。

二、@MapperScan 注解

@MapperScan 注解只不过是 MapperScannerConfigurer 的启动器而已,应用这个注解,能够代替后面的 MapperScannerConfigurer 初始化。

三、SpringBoot 主动初始化

MyBatis 提供 mybatis-spring-boot-starter 库用于在 Spring Boot 我的项目中主动初始化:

<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.1.3</version>
</dependency>

这个所谓的主动初始化实际上就是初始化 SqlSessionFactory 对象。初始化的过程由 org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration 实现,所需的配置都从 “mybatis-” 前缀的配置属性中获取,具体能够参考 org.mybatis.spring.boot.autoconfigure.MybatisProperties 类。

总结

总之,MyBatis 的初始化外围过程就是三件套的初始化。而在 Spring Boot 利用中,联合主动初始化和 @MapperScan 注解,咱们无需手工初始化上这三件套,就能间接从容器中失去 Mapper 对象。

正文完
 0