SpringBoot-Mybatis框架使⽤与源码解析
前⾔:
在上两篇⽂章 中,我们说了使⽤mybatis有三种⽅式, 这两篇⽂章已经分析了原⽣Mybatis、Spring-Mybatis的使⽤及源码分析。
现在微服务架构基本已经成为⼀种架构正确了,⽽SpringBoot技术也已经被应⽤在各个项⽬中。
SpringBoot不仅仅那些传统的好处,更多是可以与其他组件进⾏结合,使⽤户可以更⽅便的使⽤。⽐如SpringBoot-Kafka、SpringBoot-Mybatis、SpringBoot-RabbitMQ等等。
本⽂,笔者便分析⼀下SpringBoot-Mybatis的使⽤及其源码,让读者可以更深⼊的了解下SpringBoot是如何帮我们简化配置,节约开发时间的。
1.SpringBoot-Mybatis使⽤
1)添加maven依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
2)在l中添加DataSource配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: root
driver-class-name: sql.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml #注意:⼀定要对应mapper映射xml⽂件的所在路径
type-aliases-package: batis # 注意:对应实体类的路径
3)在l中添加SQL
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-////DTD Mapper 3.0//EN"
"/dtd/mybatis-3-mapper.dtd">
<mapper namespace="batis.IUser">
<select id="getUser" parameterType="int"
resultType="batis.User">
SELECT *
FROM USER
WHERE id = #{userId}
</select>
</mapper>
4)添加IUser接⼝
public interface IUser {
public User getUser(int id);
}
5)添加User实体类
@Data
public class User {
private int id;
private String name;
private String dept;
private String phone;
private String website;
}
6)在Application中添加最重要的⼀环(注意:@MapperScan对应IUser所在路径)
@SpringBootApplication
@MapperScan("batis")
public class SpringbootstudyApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(SpringbootstudyApplication.class);
springApplication.run(args);
}
}
7)添加测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes=SpringbootstudyApplication.class)
public class SpringbootstudyApplicationTests {
@Autowired
private IUser userMapper;
@Test
public void contextLoads() {
User user = User(3);
System.out.println(user);//User(id=3, name=jack, dept=devp, phone=xxx, website=www.baidu)
}
}
测试成功
2.写在源码分析之前
SpringBoot⼀般以配置居多,各种类之间的关系错综复杂。我们在分析SpringBoot的分析中,⼀定要抓住核⼼点。
⽐如当前Mybatis的分析,结合Spring-Mybatis来看,我们应该主动创建DataSource、SqlSessionFactoryBean、MapperFactoryBean,并且把这些bean添加到Spring容器中。但是从当前的使⽤配置来看,这些bean我们都没有显⽰声明,没有像Spring-Mybatis使⽤的时候那样显⽰声明在l中,所以⼀定是SpringBoot帮我们做了这些⼯作,我们的重点要放在SpringBoot
如何帮我们声明这些bean。
仔细回想⼀下,SpringBoot需要我们做的的⼯作主要就是:
* 添加mybatis-spring-boot-starter依赖
* 在Application上添加@MapperScan注解,并把IUser所在的包路径添加到注解中
所以,我们就主要从这两⾯⼊⼿,来剖析下SpringBoot-Mybatis框架
3.分析mybatis-spring-boot-starter依赖
我们在项⽬中引⼊该依赖,下⾯我们看下这个依赖的主要内容
<project xmlns="/POM/4.0.0" xmlns:xsi="/2001/XMLSchema-instance" xsi:schemaLocation="maven.apach <modelVersion>4.0.0</modelVersion>
<parent>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot</artifactId>
<version>1.1.1</version>
</parent>
<artifactId>mybatis-spring-boot-starter</artifactId>
<name>mybatis-spring-boot-starter</name>
<dependencies>
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
</project>
可以看到,主要就是引⼊mybatis-spring-boot-autoconfigure,我们来看下这个jar包的结构
结构很简单,总共只有三个类,感觉MybatisAutoConfiguration应该是很重要的类。
在META-INF中,我们⼜看到熟悉的配置spring.factories,我们在这⾥总能发现惊喜,打开这个⽂件,可以看到
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
⼜是熟悉的味道,MybatisAutoConfiguration被对应到EnableAutoConfiguration,那么MybatisAutoConfiguration类会在SpringBoot项⽬启动的时候被注⼊到Spring容器中。原因在这⾥不再赘述,读者可以看下笔者之前的博客,有详细介绍。
那么下⾯我们就来看下MybatisAutoConfiguration这个类
4.分析MybatisAutoConfiguration(SqlSessionFactory的创建)
@Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnBean(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 同样还是通过SqlSessionFactoryBean来创建SqlSessionFactory
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
if (StringUtils.hasText(ConfigLocation())) {
factory.Resource(ConfigLocation()));
}
factory.Configuration());
if (!ObjectUtils.isEmpty(this.interceptors)) {
factory.setPlugins(this.interceptors);
}
if (this.databaseIdProvider != null) {
factory.setDatabaseIdProvider(this.databaseIdProvider);
}
if (StringUtils.hasLength(TypeAliasesPackage())) {
factory.setTypeAliasesPackage(TypeAliasesPackage());
}
if (StringUtils.hasLength(TypeHandlersPackage())) {
factory.setTypeHandlersPackage(TypeHandlersPackage());
}
if (!ObjectUtils.isEmpty(solveMapperLocations())) {
// 就是我们在l中配置的mybatis.mapper-locations: classpath:mapper/*.xml
factory.setMapperLocations(solveMapperLocations());
}
Object();
}
...
可知:当前类被添加了@Configuration注解,⾥⾯的所有被@Bean注解的⽅法返回值都会被注⼊到Spring容器中
在这⾥,我们可到熟悉的SqlSessionFactory,正是Mybatis需要的组件之⼀,同样还是通过SqlSessionFactoryBean来创建,具体创
建过程笔者不再赘述,读者可参考上⼀篇 Spring-Mybatis⽂章
总结:在这⾥我们看到了SqlSessionFactory被注⼊到容器中。
疑问:可以看到,创建SqlSessionFactory的⽅法,⼊参为DataSource,那么在⽅法调⽤之前,DataSource应该已经被注⼊到容器中
了,那么DataSource是在什么时候在哪⾥被注⼊的呢?
5.DataSource在哪⾥被创建?
我们没有主动创建DataSource的bean,那么应该也是SpringBoot帮我们主动创建了,那么究竟是在哪⾥创建的呢?
我们可以开启⽇志DEBUG模式,在bean创建的过程中,都会打印相应的⽇志,在⽇志中我们搜索DataSource,可以看到以下内容
09:06:36.075 [main] DEBUG a.ConfigurationClassBeanDefinitionReader - Registered bean definition for imported class 'org.springframework.boot.au
09:06:36.075 [main] DEBUG a.ConfigurationClassBeanDefinitionReader - Registering bean definition for @Bean method org.springframework.boot.autocon
看到在org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration中,有⼀个被注⼊了@Bean的⽅法
dataSource(),感觉这个应该就是创建DataSource的⽅法了,我们进⼊该类看下:
abstract class DataSourceConfiguration {
...
@ConditionalOnClass(at.jdbc.pool.DataSource.class)
@ConditionalOnProperty(name = "pe", havingValue = "at.jdbc.pool.DataSource", matchIfMissing = true)
static class Tomcat extends DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "at")
public at.jdbc.pool.DataSource dataSource(
DataSourceProperties properties) {
at.jdbc.pool.DataSource dataSource = createDataSource(
properties, at.jdbc.pool.DataSource.class);
DatabaseDriver databaseDriver = DatabaseDriver
.fromJdbcUrl(properties.determineUrl());
String validationQuery = ValidationQuery();
if (validationQuery != null) {
dataSource.setTestOnBorrow(true);
dataSource.setValidationQuery(validationQuery);
}
return dataSource;
}
}
在这⾥确实有关于 at.jdbc.pool.DataSource的创建,⽽且Tomcat类也符合上⾯的Condition条件
那么问题⼜来了,当前类DataSourceConfiguration只是⼀个抽象类,它是什么时候被引⼊的呢?
经过⼀番查,我们看到在org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration类中有关于其创建,代码如下
@Configuration
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Tomcat.class, DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Dbcp.class, DataSourceConfiguration.Dbcp2.class,
DataSourceConfiguration.Generic.class })
@SuppressWarnings("deprecation")
protected static class PooledDataSourceConfiguration {
}
直接使⽤@Import来引⼊DataSourceConfiguration.Tomcat
总结:到此为⽌,我们可以回答我们上⽂提出的问题了,DataSource是在DataSourceConfiguration类中被注⼊到Spring容器的;
springboot框架的作用⽽DataSourceConfiguration是在DataSourceAutoConfiguration中被注⼊到Spring容器的。
6.@MapperScan()注解的分析(MapperFactoryBean的注⼊)
到⽬前为⽌,DataSource被注⼊到Spring中,SqlSessionFactory被注⼊到Spring中,还缺少MapperFactoryBean的注⼊
我们知道在@MapperScan()注解中,我们在注解value中添加了IUser所在的包路径,直觉上,MapperFactoryBean的注⼊应该跟该注解有关
下⾯我们来看下该注解的内容:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论