Mybatis源码解析之SpringBoot集成mybatis-spring-boot-starter分析
2021-05-30 08:01
标签:ons ati boot arc factory illegal find resource star 本文将针对SpringBoot和Mybatis的集成进行解析,若无特殊说明,本文解析的jar包和版本为:org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1。 一、jar包介绍 @ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX) public static final String MYBATIS_PREFIX = "mybatis"; /** /** /** /** /** /** /** /** mybatis: @org.springframework.context.annotation.Configuration 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 public MybatisAutoConfiguration(MybatisProperties properties, @PostConstruct @Bean return factory.getObject(); @Bean 四、MapperScannerRegistrarNotFoundConfiguration @org.springframework.context.annotation.Configuration @PostConstruct @Override logger.debug("Searching for mappers annotated with @Mapper"); ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); try { List scanner.setAnnotationClass(Mapper.class); Mybatis源码解析之SpringBoot集成mybatis-spring-boot-starter分析 标签:ons ati boot arc factory illegal find resource star 原文地址:https://www.cnblogs.com/cpjl456/p/14754608.html
该jar包是mybatis和springboot的集成jar包,因此对mybatis、mybatis-spring和springboot部分的jar包都存在依赖。
二、配置
在mybatis-spring-boot-starter中,支持的配置内容对应MybatisProperties类。
public class MybatisProperties {
* 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位置。
mapper-locations: classpath*:mybatis/mapper/*/*.xml
1
2
三、MybatisAutoConfiguration
基于自动配置类MybatisAutoConfiguration对配置内容进行解析。
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnBean(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {
ObjectProvider
ResourceLoader resourceLoader,
ObjectProvider
ObjectProvider> configurationCustomizersProvider) {
this.properties = properties;
this.interceptors = interceptorsProvider.getIfAvailable();
this.resourceLoader = resourceLoader;
this.databaseIdProvider = databaseIdProvider.getIfAvailable();
this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
}
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)");
}
}
@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());
}
}
@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中已经实现了默认的注入。
我们知道,在注入了SqlSessionFactory后,接下来只要注入mapper接口的bean就可以完成mybatis的集成。
在SpringBoot中,同样支持通过MapperScan注解的方式通过MapperFactoryBean注入mapper接口,这一点同spring和mybatis的集成一样。
如果,我们没有注入任何的MapperFactoryBean,那么SpringBoot还支持Mapper注解的单个注入方式。
@Import({ AutoConfiguredMapperScannerRegistrar.class })
@ConditionalOnMissingBean(MapperFactoryBean.class)
public static class MapperScannerRegistrarNotFoundConfiguration {
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方法。
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
if (this.resourceLoader != null) {
scanner.setResourceLoader(this.resourceLoader);
}
if (logger.isDebugEnabled()) {
for (String pkg : packages) {
logger.debug("Using auto-configuration base package ‘{}‘", pkg);
}
}
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分析
文章链接:http://soscw.com/index.php/essay/89466.html