码迷,mamicode.com
首页 > 编程语言 > 详细

Mybatis源码解析之SpringBoot集成mybatis-spring-boot-starter分析

时间:2021-05-24 05:15:29      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:ons   ati   boot   arc   factory   illegal   find   resource   star   

本文将针对SpringBoot和Mybatis的集成进行解析,若无特殊说明,本文解析的jar包和版本为:org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1。

一、jar包介绍
该jar包是mybatis和springboot的集成jar包,因此对mybatis、mybatis-spring和springboot部分的jar包都存在依赖。


二、配置
在mybatis-spring-boot-starter中,支持的配置内容对应MybatisProperties类。

@ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties {

public static final String MYBATIS_PREFIX = "mybatis";

/**
* Location of MyBatis xml config file.
*/
private String configLocation;

/**
* Locations of MyBatis mapper files.
*/
private String[] mapperLocations;

/**
* Packages to search type aliases. (Package delimiters are ",; \t\n")
*/
private String typeAliasesPackage;

/**
* Packages to search for type handlers. (Package delimiters are ",; \t\n")
*/
private String typeHandlersPackage;

/**
* Indicates whether perform presence check of the MyBatis xml config file.
*/
private boolean checkConfigLocation = false;

/**
* Execution mode for {@link org.mybatis.spring.SqlSessionTemplate}.
*/
private ExecutorType executorType;

/**
* Externalized properties for MyBatis configuration.
*/
private Properties configurationProperties;

/**
* A Configuration object for customize default settings. If {@link #configLocation}
* is specified, this property is not used.
*/
@NestedConfigurationProperty
private Configuration configuration;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
如下文的例子指定了mapper位置。

mybatis:
mapper-locations: classpath*:mybatis/mapper/*/*.xml
1
2
三、MybatisAutoConfiguration
基于自动配置类MybatisAutoConfiguration对配置内容进行解析。

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnBean(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {

private static final Logger logger = LoggerFactory.getLogger(MybatisAutoConfiguration.class);

private final MybatisProperties properties;

private final Interceptor[] interceptors;

private final ResourceLoader resourceLoader;

private final DatabaseIdProvider databaseIdProvider;

private final List<ConfigurationCustomizer> configurationCustomizers;

public MybatisAutoConfiguration(MybatisProperties properties,
ObjectProvider<Interceptor[]> interceptorsProvider,
ResourceLoader resourceLoader,
ObjectProvider<DatabaseIdProvider> databaseIdProvider,
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
this.properties = properties;
this.interceptors = interceptorsProvider.getIfAvailable();
this.resourceLoader = resourceLoader;
this.databaseIdProvider = databaseIdProvider.getIfAvailable();
this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
}

@PostConstruct
public void checkConfigFileExists() {
if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
Assert.state(resource.exists(), "Cannot find config location: " + resource
+ " (please add config file or check your Mybatis configuration)");
}
}

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
factory.setVfs(SpringBootVFS.class);
if (StringUtils.hasText(this.properties.getConfigLocation())) {
factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
}
Configuration configuration = this.properties.getConfiguration();
if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
configuration = new Configuration();
}
if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
customizer.customize(configuration);
}
}
factory.setConfiguration(configuration);
if (this.properties.getConfigurationProperties() != null) {
factory.setConfigurationProperties(this.properties.getConfigurationProperties());
}
if (!ObjectUtils.isEmpty(this.interceptors)) {
factory.setPlugins(this.interceptors);
}
if (this.databaseIdProvider != null) {
factory.setDatabaseIdProvider(this.databaseIdProvider);
}
if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
}
if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
}
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
factory.setMapperLocations(this.properties.resolveMapperLocations());
}

return factory.getObject();
}

@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
ExecutorType executorType = this.properties.getExecutorType();
if (executorType != null) {
return new SqlSessionTemplate(sqlSessionFactory, executorType);
} else {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
可以看到,在没有手动注入的情况下,根据配置的属性注入了SqlSessionTemplate和SqlSessionFactory,值域SqlSessionFactoryBean依赖的属性DataSource,在springboot的jabc包中的自动配置类DataSourceAutoConfiguration中已经实现了默认的注入。

四、MapperScannerRegistrarNotFoundConfiguration
我们知道,在注入了SqlSessionFactory后,接下来只要注入mapper接口的bean就可以完成mybatis的集成。
在SpringBoot中,同样支持通过MapperScan注解的方式通过MapperFactoryBean注入mapper接口,这一点同spring和mybatis的集成一样。
如果,我们没有注入任何的MapperFactoryBean,那么SpringBoot还支持Mapper注解的单个注入方式。

@org.springframework.context.annotation.Configuration
@Import({ AutoConfiguredMapperScannerRegistrar.class })
@ConditionalOnMissingBean(MapperFactoryBean.class)
public static class MapperScannerRegistrarNotFoundConfiguration {

@PostConstruct
public void afterPropertiesSet() {
logger.debug("No {} found.", MapperFactoryBean.class.getName());
}
}
1
2
3
4
5
6
7
8
9
10
在MybatisAutoConfiguration$MapperScannerRegistrarNotFoundConfiguration中可以看到,如果没有MapperFactoryBean类的bean,其可以通过AutoConfiguredMapperScannerRegistrar注入bean。
AutoConfiguredMapperScannerRegistrar实现了ImportBeanDefinitionRegistrar接口,注入bean的方法是registerBeanDefinitions方法。

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

logger.debug("Searching for mappers annotated with @Mapper");

ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);

try {
if (this.resourceLoader != null) {
scanner.setResourceLoader(this.resourceLoader);
}

List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
if (logger.isDebugEnabled()) {
for (String pkg : packages) {
logger.debug("Using auto-configuration base package ‘{}‘", pkg);
}
}

scanner.setAnnotationClass(Mapper.class);
scanner.registerFilters();
scanner.doScan(StringUtils.toStringArray(packages));
} catch (IllegalStateException ex) {
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
可以看到,其和MapperScanner注解的注入方式类似,生成了一个扫描类ClassPathMapperScanner,扫描路径下被Mapper注解的mapper接口并注入。ClassPathMapperScanner的源码前面在spring和mybatis的集成成一家进行了简单的分析,不在赘述。

Mybatis源码解析之SpringBoot集成mybatis-spring-boot-starter分析

标签:ons   ati   boot   arc   factory   illegal   find   resource   star   

原文地址:https://www.cnblogs.com/cpjl456/p/14754608.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!