mybatis-spring-boot-starter原理分析⼀、前⾔
mybatis-spring-boot-starter是什么?
mybatis-spring-boot-starter可以帮助你快速创建基于Spring Boot的MyBatis应⽤程序。
mybatis-spring-boot-starter可以达到什么效果?
● 构建独⽴的MyBatis应⽤程序
● 零模板
● 更少的XML配置⽂件
引⼊mybatis-spring-boot-starter模块之后,其可以:
● ⾃动检测DataSource
● 使⽤SqlSessionFactoryBean注册SqlSessionFactory 实例,并设置DataSource数据源
● 基于SqlSessionFactory⾃动注册SqlSessionTemplate实例
● ⾃动扫描@Mapper注解类,并通过SqlSessionTemplate注册到Spring Context中
mybatis-spring-boot-starter就是参照Spring Boot的设计思想,化繁为简,以简单注解的⽅式让⽤户快速上⼿。
下⾯我们简单的创建⼀个项⽬,让他跑起来:
⾸先,我们引⼊依赖:
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
配置数据源
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/auto?useUnicode=true&useSSL=false&characterEncoding=utf8
username: root
password: root
driver-class-name: sql.jdbc.Driver
创建Mapper
public interface UserMapper {
@Select("SELECT * FROM Person WHERE id = #{id}")
Person selectUser(int id);
@Delete("delete from person where id = #{id}")
void deleteByPrimaryKey(int id);
}
启动类:
@MapperScan("com.fendo.auto.mapper") //扫描的mapper
@SpringBootApplication
public class AutoApplication {
public static void main(String[] args) {
SpringApplication.run(AutoApplication.class, args);
}
}
这样就完成了⼀个简单的集成
⼆、原理分析
mybatis-spring-boot-starter的作⽤就是,在SpringBoot启动时,去扫描所有Mapper接⼝,然后为其增加⼀个代理实现类,在调⽤的过程中,我们实际调⽤的是这个代理对象。⽤过springboot的同学都是知道,springboot配置简单,更提供了⼤量的starter⽅便集成各个组件。每个组件基本只要依赖了jar包,基本不需要或者需要少量的配置信息就可以直接使⽤了,那么在这简单的starter背后的原理是什么呢?
统⼀的命名规范 XXX-spring-boot-starter (⾮必须)
你如果去看每个starter的的名字,⽐如mybatis的starter名字如下:
<dependency>
<groupId&batis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
你会发现每个starter的artifactId都是以spring-boot-starter结尾,这个是普遍认同的⼀个规范,不是必须按照这个名字来,也可以⾃定义名字,原因下⾯介绍。
统⼀的配置⽂件 spring.factories
必须在classpath下的META-INF⽂件夹下创建⼀个spring.factories,本质是⼀个Properties,所以得按照key-value的形式进⾏配置。⾃动配置的key是org.springframework.boot.autoconfigure.EnableAutoConfiguration。我们看下mybatis的配置:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
我们看到,这个⽂件配置了⼀个key:value格式的数据
1)key是:org.springframework.boot.autoconfigure.EnableAutoConfiguration
2)value是:
key声明的是⼀个接⼝,value则是这个接⼝对应的实现类,如果有多个则以","符号分割。
简单来说,spring.factories就像是⼯⼚⼀样配置了⼤量的接⼝对应的实现类,我们通过这些配置 + 反射处理就可以拿到相应的实现类。这
种类似于插件式的设计⽅式,只要引⼊对应的jar包,那么对应的spring.factories就会被扫描到,对应的实现类也就会被实例化,如果不需
要的时候,直接把jar包移除即可。
注解说明:
Configuration 是springboot提供的,表⽰这是⼀个配置类,其实它的作⽤跟@Bean是⼀样的,都是让spring实例化该类。
@ConditionalOnClass
springboot是啥
表⽰存在某些类的时候,才进⾏初始化。
@AutoConfigureBefore
表⽰必须先初始化某个类
@AutoConfigureAfter
表⽰初始化完成之后加载某个类
@ConditionalOnBean
只有在上下⽂中存在某个类才运⾏
@EnableConfigurationProperties
ConfigurationProperties注解主要⽤来把properties配置⽂件转化为bean来使⽤的
⽽@EnableConfigurationProperties注解的作⽤是@ConfigurationProperties注解⽣效。
如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置⽂件转化的bean的。
@ConditionalOnMissingBean
作⽤在@bean定义上,它的作⽤就是在容器加载它作⽤的bean时
检查容器中是否存在⽬标类型(ConditionalOnMissingBean注解的value值)的bean了
如果存在这跳过原始bean的BeanDefinition加载动作。
简单理解就是@ConditionalOnBean是依赖,@ConditionalOnMissBean是排斥,@Conditional为条件
@ConditionalOnSingleCandidate 当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true
@ConditionalOnMissingBean    当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系
@ConditionalOnBean            与上⾯相反,要求bean存在
@ConditionalOnMissingClass    当给定的类名在类路径上不存在时返回true,各类型间是and的关系
@ConditionalOnClass            与上⾯相反,要求类存在
@ConditionalOnCloudPlatform    当所配置的CloudPlatform为激活时返回true
@ConditionalOnExpression    spel表达式执⾏为true
@ConditionalOnJava            运⾏时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配
@ConditionalOnProperty        要求配置属性匹配条件
@ConditionalOnJndi            给定的jndi的Location 必须存在⼀个.否则,返回不匹配
@ConditionalOnNotWebApplication web环境不存在时
@ConditionalOnWebApplication web环境存在时
@ConditionalOnResource        要求制定的资源存在
mybatis-spring-boot-starter中最主要的⼀个类就是MybatisAutoConfiguration,MybatisAutoConfiguration 是spring boot 下mybatis 默认的配置类,只要开启了注释了 @EnableAutoConfiguration 就可以了,spring boot 会默认执⾏。在SpringBoot启动的过程中 @Sprin
gBootApplication 中组合了 EnableAutoConfiguration ,属于spring boot ⾃动配置和启动过程,SpringBoot启动时会进⼊到MybatisAutoConfiguration这个类⾥,这是⼀个⾃动配置类,这⾥⾯初始化了SqlSessionFactory、SqlSessionTemplate等⼀些我们在Spring项⽬中需要⼿动配置的,源码如下该类如下:
//Configuration注解:说明这是spring的配置项,容器初始化的时候要进⾏解析处理
@t.annotation.Configuration
//ConditionalOnClass注解:有类SqlSessionFactory(Mybatis),SqlSessionFactoryBean(Mybatis-Spring)的时候才进⾏解析处理
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
//ConditionalOnBean注解:容器中有DataSource Bean的时候才进⾏解析处理
@ConditionalOnSingleCandidate(DataSource.class)
//ConfigurationProperties注解主要⽤来把properties配置⽂件转化为bean来使⽤的
//ConfigurationProperties注解主要⽤来把properties配置⽂件转化为bean来使⽤的
//⽽EnableConfigurationProperties注解的作⽤是ConfigurationProperties注解⽣效。
//如果只配置@ConfigurationProperties注解,在IOC容器中是获取不到properties配置⽂件转化的bean的。
//MybatisProperties是mybatis的配置类,将properties中的配置⽂件转换成MybatisProperties对象
//MybatisProperties上有@ConfigurationProperties(prefix = "mybatis")注解。
//EnableConfigurationProperties注解和MybatisProperties类:配置⾃⼰的Mybatis 属性,在Application.Properties中。
@EnableConfigurationProperties(MybatisProperties.class)
//AutoConfigureAfter注解: 在DataSourceAutoConfiguration,MybatisLanguageDriverAutoConfiguration后解析
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
private static final Logger logger = Logger(MybatisAutoConfiguration.class);
private final MybatisProperties properties;
private final Interceptor[] interceptors;
private final TypeHandler[] typeHandlers;
private final LanguageDriver[] languageDrivers;
private final ResourceLoader resourceLoader;
private final DatabaseIdProvider databaseIdProvider;
private final List<ConfigurationCustomizer> configurationCustomizers;
/**
* 构造⽅法
* @param properties
* @param interceptorsProvider
* @param typeHandlersProvider
* @param languageDriversProvider
* @param resourceLoader
* @param databaseIdProvider
* @param configurationCustomizersProvider
*/
public MybatisAutoConfiguration(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider,
ObjectProvider<TypeHandler[]> typeHandlersProvider, ObjectProvider<LanguageDriver[]> languageDriversProvider,                                    ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider,
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
this.properties = properties;
this.interceptors = IfAvailable();
this.languageDrivers = IfAvailable();
this.databaseIdProvider = IfAvailable();
}
@Override
public void afterPropertiesSet() {
checkConfigFileExists();
}
private void checkConfigFileExists() {
if (this.properties.isCheckConfigLocation() && StringUtils.hasText(ConfigLocation())) {
Resource resource = Resource(ConfigLocation());
Assert.ists(),
"Cannot find config location: " + resource + " (please add config file or check your Mybatis configuration)");
}
}
/**
* 创建SqlSessionFactory

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。