@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
// 开启Mybatis的属性配置
@EnableConfigurationProperties(MybatisProperties.class)
// 必须先加载数据源和SQL模版解析器
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class})
public class MybatisAutoConfiguration implements InitializingBean {
// 自动注入Mybatis的属性配置
public final MybatisProperties properties;
// 自动注入Mybatis的拦截器
public final Interceptor[] interceptors;
// 自动注入Mybatis的类型转换器
public final TypeHandler[] typeHandlers;
// 自动注入Mybatis中SQL的模版解析器
public final LanguageDriver[] languageDrivers;
// 自动注入资源加载器
public final ResourceLoader resourceLoader;
// 自动注入数据库ID提供对象
public final DatabaseIdProvider databaseIdProvider;
// 自动注入所有对Mybatis的核心Configuration配置类对象进行自定义的类
public final List<ConfigurationCustomizer> configurationCustomizers;
// 自动注入所有对Mybatis生成SqlSessionFactory的Customizer自定义的对象
public final List<SqlSessionFactoryBeanCustomizer> sqlSessionFactoryBeanCustomizers;
// 当开启了mybatis配置文件校验机制的情况下,校验mybatis-config.xml是否存在
@Override
public void afterPropertiesSet() {
checkConfigFileExists();
}
// 当开启了mybatis配置文件校验机制的情况下,校验mybatis-config.xml是否存在
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)");
}
}
// 注册Mybatis和核心类SqlSessionFactory
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
// 创建SqlSessionFactoryBean对象,通过SqlSessionFactoryBean创建SqlSessionFactory
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
// 设置数据源
factory.setDataSource(dataSource);
if (properties.getConfiguration() == null || properties.getConfiguration().getVfsImpl() == null) {
factory.setVfs(SpringBootVFS.class);
}
// 设置mybatis配置文件的路径
if (StringUtils.hasText(this.properties.getConfigLocation())) {
factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
}
// 创建Configuration对象并将属性配置中的属性进行设置
this.applyConfiguration(factory);
if (this.properties.getConfigurationProperties() != null) {
factory.setConfigurationProperties(this.properties.getConfigurationProperties());
}
// 设置一些Mybatis的组件
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 (this.properties.getTypeAliasesSuperType() != null) {
factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
}
if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
}
if (!ObjectUtils.isEmpty(this.typeHandlers)) {
factory.setTypeHandlers(this.typeHandlers);
}
// 将在属性文件中属性mapper路径解析成Resource,会将正则表达式解析
Resource[] mapperLocations = this.properties.resolveMapperLocations();
if (!ObjectUtils.isEmpty(mapperLocations)) {
factory.setMapperLocations(mapperLocations);
}
Set<String> factoryPropertyNames = Stream
.of(new BeanWrapperImpl(SqlSessionFactoryBean.class).getPropertyDescriptors())
.map(PropertyDescriptor::getName)
.collect(Collectors.toSet());
Class<? extends LanguageDriver> defaultLanguageDriver = this.properties.getDefaultScriptingLanguageDriver();
if (factoryPropertyNames.contains("scriptingLanguageDrivers") && !ObjectUtils.isEmpty(this.languageDrivers)) {
// Need to mybatis-spring 2.0.2+
factory.setScriptingLanguageDrivers(this.languageDrivers);
if (defaultLanguageDriver == null && this.languageDrivers.length == 1) {
defaultLanguageDriver = this.languageDrivers[0].getClass();
}
}
if (factoryPropertyNames.contains("defaultScriptingLanguageDriver")) {
// Need to mybatis-spring 2.0.2+
factory.setDefaultScriptingLanguageDriver(defaultLanguageDriver);
}
// 执行所有对SqlSessionFactoryBean进行自定义的配置类
applySqlSessionFactoryBeanCustomizers(factory);
return factory.getObject();
}
// 创建Configuration对象并将属性配置中的属性进行设置
public void applyConfiguration(SqlSessionFactoryBean factory) {
// 获取配置信息
MybatisProperties.CoreConfiguration coreConfiguration = this.properties.getConfiguration();
// 创建Configuration对象
Configuration configuration = null;
// 如果不存在mybatis配置文件或者设置了Mybatis相关配置,创建默认的Configuration对象
if (coreConfiguration != null || !StringUtils.hasText(this.properties.getConfigLocation())) {
configuration = new Configuration();
}
// 将在配置属性中配置的信息迁移到Mybatis的configuration对象中
if (configuration != null && coreConfiguration != null) {
coreConfiguration.applyTo(configuration);
}
// 执行所有对Configuration自定义的对象
if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
customizer.customize(configuration);
}
}
// 将Configuration对象设置到工厂中
factory.setConfiguration(configuration);
}
// 执行所有对SqlSessionFactoryBean进行自定义的配置类
public void applySqlSessionFactoryBeanCustomizers(SqlSessionFactoryBean factory) {
if (!CollectionUtils.isEmpty(this.sqlSessionFactoryBeanCustomizers)) {
for (SqlSessionFactoryBeanCustomizer customizer : this.sqlSessionFactoryBeanCustomizers) {
customizer.customize(factory);
}
}
}
// 注册Mybatis的核心SqlSession(SqlSessionTemplate)
// 对于Mybatis来说,每次执行都需要创建一个新的SqlSession,但是对于Spring-Mybatis来说只需要一个SqlSession就可以
// 它并不是真正工作的SqlSession,它内部代理了一个SqlSession,会完全控制SqlSession的执行
// 并且代理的SqlSession的生命周期都会由SqlSessionTemplate来完成
// 需要新的SqlSession的时候,使用SqlSessionFactory创建,使用完成进行关闭
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
// 获取执行器类型
ExecutorType executorType = this.properties.getExecutorType();
// 根据不同的执行器创建不同的SqlSession
if (executorType != null) {
return new SqlSessionTemplate(sqlSessionFactory, executorType);
}
return new SqlSessionTemplate(sqlSessionFactory);
}
}
// 导入Mybatis的Mapper接口扫描器
public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, EnvironmentAware, ImportBeanDefinitionRegistrar {
public BeanFactory beanFactory;
public Environment environment;
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// SpringBoot会在解析启动类的时候,会将启动类中标记的扫描包(或者默认扫描的包)设置为一个Bean对象保存,供大家使用
if (!AutoConfigurationPackages.has(this.beanFactory)) {
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
return;
}
// 获取SpringBoot的自动扫描的所有包
List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
// Mybatis也会将这些包作为Mapper的扫描包
if (logger.isDebugEnabled()) {
packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
}
// 创建Mapper扫描器
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
// 设置相关属性,处理属性占位符
builder.addPropertyValue("processPropertyPlaceHolders", true);
// 需要扫描标注了Mapper注解的接口
builder.addPropertyValue("annotationClass", Mapper.class);
// 添加需要扫描的包名
builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages));
BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class);
// 获取MapperScannerConfigurer对象中的所有属性名
Set<String> propertyNames = Stream.of(beanWrapper.getPropertyDescriptors()).map(PropertyDescriptor::getName).collect(Collectors.toSet());
// 设置Mapper懒加载
if (propertyNames.contains("lazyInitialization")) {
// Need to mybatis-spring 2.0.2+
builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}");
}
// 设置Mapper的默认作用域
if (propertyNames.contains("defaultScope")) {
// Need to mybatis-spring 2.0.6+
builder.addPropertyValue("defaultScope", "${mybatis.mapper-default-scope:}");
}
// 是否注册SqlSession对象,默认为true
boolean injectSqlSession = environment.getProperty("mybatis.inject-sql-session-on-mapper-scan", Boolean.class, Boolean.TRUE);
if (injectSqlSession && this.beanFactory instanceof ListableBeanFactory) {
ListableBeanFactory listableBeanFactory = (ListableBeanFactory) this.beanFactory;
// 获取SqlSessionTemplate对应的BeanName
Optional<String> sqlSessionTemplateBeanName = Optional.ofNullable(getBeanNameForType(SqlSessionTemplate.class, listableBeanFactory));
// 获取SqlSessionFactory对应的BeanName
Optional<String> sqlSessionFactoryBeanName = Optional.ofNullable(getBeanNameForType(SqlSessionFactory.class, listableBeanFactory));
// 设置SqlSessionTemplate
if (sqlSessionTemplateBeanName.isPresent() || !sqlSessionFactoryBeanName.isPresent()) {
builder.addPropertyValue("sqlSessionTemplateBeanName", sqlSessionTemplateBeanName.orElse("sqlSessionTemplate"));
} else {
builder.addPropertyValue("sqlSessionFactoryBeanName", sqlSessionFactoryBeanName.get());
}
}
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册该Mapper的扫描器
registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());
}
public String getBeanNameForType(Class<?> type, ListableBeanFactory factory) {
String[] beanNames = factory.getBeanNamesForType(type);
return beanNames.length > 0 ? beanNames[0] : null;
}
}
@org.springframework.context.annotation.Configuration(proxyBeanMethods = false)
// 导入Mybatis的Mapper接口扫描器
@Import(AutoConfiguredMapperScannerRegistrar.class)
@ConditionalOnMissingBean({MapperFactoryBean.class, MapperScannerConfigurer.class})
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
@Override
public void afterPropertiesSet() {
logger.debug("Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");
}
}
/**
* {@link MapperScannerConfigurer}
* // 最小配置案例
* <pre class="code">
* MapperScan("org.mybatis.spring.sample.mapper")
* public class AppConfig {
*
* @Bean
* public DataSource dataSource() {
* // 自动初始化脚本
* return new EmbeddedDatabaseBuilder().addScript("schema.sql").build();
* }
*
* @Bean
* public DataSourceTransactionManager transactionManager() {
* return new DataSourceTransactionManager(dataSource());
* }
*
* @Bean
* public SqlSessionFactory sqlSessionFactory() throws Exception {
* SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
* sessionFactory.setDataSource(dataSource());
* return sessionFactory.getObject();
* }
* }
* </pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {
// 需要扫描的包
@AliasFor("basePackages")
String[] value() default {};
// 需要扫描的包
@AliasFor("value")
String[] basePackages() default {};
// 需要扫描的类
Class<?>[] basePackageClasses() default {};
// beanName生成器
Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
// 需要过滤的注解类型
Class<? extends Annotation> annotationClass() default Annotation.class;
// 需要过滤的接口类型
Class<?> markerInterface() default Class.class;
// SqlSessionTemplate的BeanName
String sqlSessionTemplateRef() default "";
// SqlSessionFactory的BeanName
String sqlSessionFactoryRef() default "";
// 创建Mapper接口的MapperFactoryBean对象
Class<? extends MapperFactoryBean> factoryBean() default MapperFactoryBean.class;
// 懒加载
String lazyInitialization() default "";
// Mapper默认的作用域
String defaultScope() default AbstractBeanDefinition.SCOPE_DEFAULT;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.RepeatingRegistrar.class)
public @interface MapperScans {
MapperScan[] value();
}
// MapperScan注解需要导入的类
public class MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware {
// 注册Bean
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取@MapperScan的属性信息
AnnotationAttributes mapperScanAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
// 如果存在该注解,才开始注册Bean
if (mapperScanAttrs != null) {
// 注册Mapper
registerBeanDefinitions(importingClassMetadata, mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
}
}
// 注册Mapper
void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) {
// 注册Mapper扫描器
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
// 将注解中的属性全部设置到扫描器中
builder.addPropertyValue("processPropertyPlaceHolders", true);
Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
if (!Annotation.class.equals(annotationClass)) {
builder.addPropertyValue("annotationClass", annotationClass);
}
Class<?> markerInterface = annoAttrs.getClass("markerInterface");
if (!Class.class.equals(markerInterface)) {
builder.addPropertyValue("markerInterface", markerInterface);
}
Class<? extends BeanNameGenerator> generatorClass = annoAttrs.getClass("nameGenerator");
if (!BeanNameGenerator.class.equals(generatorClass)) {
builder.addPropertyValue("nameGenerator", BeanUtils.instantiateClass(generatorClass));
}
Class<? extends MapperFactoryBean> mapperFactoryBeanClass = annoAttrs.getClass("factoryBean");
if (!MapperFactoryBean.class.equals(mapperFactoryBeanClass)) {
builder.addPropertyValue("mapperFactoryBeanClass", mapperFactoryBeanClass);
}
String sqlSessionTemplateRef = annoAttrs.getString("sqlSessionTemplateRef");
if (StringUtils.hasText(sqlSessionTemplateRef)) {
builder.addPropertyValue("sqlSessionTemplateBeanName", annoAttrs.getString("sqlSessionTemplateRef"));
}
String sqlSessionFactoryRef = annoAttrs.getString("sqlSessionFactoryRef");
if (StringUtils.hasText(sqlSessionFactoryRef)) {
builder.addPropertyValue("sqlSessionFactoryBeanName", annoAttrs.getString("sqlSessionFactoryRef"));
}
List<String> basePackages = new ArrayList<>();
basePackages.addAll(Arrays.stream(annoAttrs.getStringArray("basePackages")).filter(StringUtils::hasText).collect(Collectors.toList()));
basePackages.addAll(Arrays.stream(annoAttrs.getClassArray("basePackageClasses")).map(ClassUtils::getPackageName).collect(Collectors.toList()));
// 如果没有需要扫描的包
if (basePackages.isEmpty()) {
// 将标注@MapperScan注解的类作为扫描的包
basePackages.add(getDefaultBasePackage(annoMeta));
}
String lazyInitialization = annoAttrs.getString("lazyInitialization");
if (StringUtils.hasText(lazyInitialization)) {
builder.addPropertyValue("lazyInitialization", lazyInitialization);
}
String defaultScope = annoAttrs.getString("defaultScope");
if (!AbstractBeanDefinition.SCOPE_DEFAULT.equals(defaultScope)) {
builder.addPropertyValue("defaultScope", defaultScope);
}
builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages));
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册Mapper的扫描器
registry.registerBeanDefinition(beanName, builder.getBeanDefinition());
}
// 生成beanName
public static String generateBaseBeanName(AnnotationMetadata importingClassMetadata, int index) {
return importingClassMetadata.getClassName() + "#" + MapperScannerRegistrar.class.getSimpleName() + "#" + index;
}
// 获取指定类的包名
public static String getDefaultBasePackage(AnnotationMetadata importingClassMetadata) {
return ClassUtils.getPackageName(importingClassMetadata.getClassName());
}
// 重复标记的@MapperScan注解注册类
static class RepeatingRegistrar extends MapperScannerRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取@MapperScans的属性信息
AnnotationAttributes mapperScansAttrs = AnnotationAttributes.fromMap(importingClassMetadata.getAnnotationAttributes(MapperScans.class.getName()));
// 存在注解才处理
if (mapperScansAttrs != null) {
// 获取value值,也就是所有的MapperScan
AnnotationAttributes[] annotations = mapperScansAttrs.getAnnotationArray("value");
// 遍历所有的MapperScan,将每一个Mapper都进行扫描
for (int i = 0; i < annotations.length; i++) {
registerBeanDefinitions(importingClassMetadata, annotations[i], registry, generateBaseBeanName(importingClassMetadata, i));
}
}
}
}
}
// SqlSession的模板对象,就是一个SqlSession
public class SqlSessionTemplate implements SqlSession, DisposableBean {
// SqlSession工厂
private final SqlSessionFactory sqlSessionFactory;
// 执行器类型
private final ExecutorType executorType;
// 代理的SqlSession
private final SqlSession sqlSessionProxy;
// 持久性异常转换器,将异常持久化异常统一转换为Spring的DataAccessException的转换器
private final PersistenceExceptionTranslator exceptionTranslator;
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
}
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
}
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
// 创建SqlSession的代理对象
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor());
}
/********************************除了事务相关方法,提交,回滚,关闭方法会抛出异常,其他的全是直接调用代理对象的方法*************************************/
@Override
public <T> T selectOne(String statement) {
return this.sqlSessionProxy.selectOne(statement);
}
@Override
public <T> T selectOne(String statement, Object parameter) {
return this.sqlSessionProxy.selectOne(statement, parameter);
}
@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
return this.sqlSessionProxy.selectMap(statement, mapKey);
}
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
return this.sqlSessionProxy.selectMap(statement, parameter, mapKey);
}
@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
}
@Override
public <T> Cursor<T> selectCursor(String statement) {
return this.sqlSessionProxy.selectCursor(statement);
}
@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter) {
return this.sqlSessionProxy.selectCursor(statement, parameter);
}
@Override
public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
}
@Override
public <E> List<E> selectList(String statement) {
return this.sqlSessionProxy.selectList(statement);
}
@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.sqlSessionProxy.selectList(statement, parameter);
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return this.sqlSessionProxy.selectList(statement, parameter, rowBounds);
}
@Override
public void select(String statement, ResultHandler handler) {
this.sqlSessionProxy.select(statement, handler);
}
@Override
public void select(String statement, Object parameter, ResultHandler handler) {
this.sqlSessionProxy.select(statement, parameter, handler);
}
@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
}
@Override
public int insert(String statement) {
return this.sqlSessionProxy.insert(statement);
}
@Override
public int insert(String statement, Object parameter) {
return this.sqlSessionProxy.insert(statement, parameter);
}
@Override
public int update(String statement) {
return this.sqlSessionProxy.update(statement);
}
@Override
public int update(String statement, Object parameter) {
return this.sqlSessionProxy.update(statement, parameter);
}
@Override
public int delete(String statement) {
return this.sqlSessionProxy.delete(statement);
}
@Override
public int delete(String statement, Object parameter) {
return this.sqlSessionProxy.delete(statement, parameter);
}
@Override
public <T> T getMapper(Class<T> type) {
return getConfiguration().getMapper(type, this);
}
// 不支持提交事务,因为事务是交给Spring管理的
@Override
public void commit() {
throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}
// 不支持提交事务,因为事务是交给Spring管理的
@Override
public void commit(boolean force) {
throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
}
// 不支持回滚事务,因为事务是交给Spring管理的
@Override
public void rollback() {
throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
// 不支持回滚事务,因为事务是交给Spring管理的
@Override
public void rollback(boolean force) {
throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
}
// 不支持关闭操作,因为是交给Spring管理的
@Override
public void close() {
throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
}
@Override
public void clearCache() {
this.sqlSessionProxy.clearCache();
}
@Override
public Configuration getConfiguration() {
return this.sqlSessionFactory.getConfiguration();
}
@Override
public Connection getConnection() {
return this.sqlSessionProxy.getConnection();
}
@Override
public List<BatchResult> flushStatements() {
return this.sqlSessionProxy.flushStatements();
}
@Override
public void destroy() throws Exception {
}
}
// 拦截目标SqlSession的拦截器,用于SqlSession代理对象
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 获取SqlSession,如果当前线程存在就获取,否则创建并注册到当前线程中
SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);
try {
// 执行SqlSession的目标方法
Object result = method.invoke(sqlSession, args);
// 如果才当前线程获取到的SqlSession,与给定的SqlSession是一同个,表示是指定SqlSession的事务,否则不是
if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// 提交当前会话的事务
sqlSession.commit(true);
}
// 返回结果
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
// 只处理PersistenceException异常
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// 关闭SqlSession
SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
// 将SqlSession置空
sqlSession = null;
// 将异常转换后抛出
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
// 执行完成,关闭SqlSession
if (sqlSession != null) {
SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
public final class SqlSessionUtils {
public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
// 从ThreadLocal中获取SqlSession,如果存在事务,可能就获取的到
SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
// 获取并校验已存在的SqlSession
SqlSession session = sessionHolder(executorType, holder);
// 如果有已经存在的SqlSession,直接返回
if (session != null) {
return session;
}
// 如果TheadLocal中没有,使用SqlSessionFactory创建
LOGGER.debug(() -> "Creating a new SqlSession");
session = sessionFactory.openSession(executorType);
// 将创建的SqlSession保存到TheadLocal中
registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
return session;
}
// 注册新创建的SqlSession
private static void registerSessionHolder(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator, SqlSession session) {
SqlSessionHolder holder;
// 如果事务是活跃的
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 获取环境对象
Environment environment = sessionFactory.getConfiguration().getEnvironment();
// 如果事务工厂类型是SpringManagedTransactionFactory类型
if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {
LOGGER.debug(() -> "Registering transaction synchronization for SqlSession [" + session + "]");
// 创建SqlSessionHodler
holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
// 将当前SqlSession绑定到ThreadLocal中
TransactionSynchronizationManager.bindResource(sessionFactory, holder);
// 注册事务同步器
TransactionSynchronizationManager.registerSynchronization(new SqlSessionSynchronization(holder, sessionFactory));
// 设置当前SqlSession与事务同步了
holder.setSynchronizedWithTransaction(true);
// SqlSession引用次数+1
holder.requested();
}
// 如果在Mybatis中指定要使用某种事务
else {
// 根据Mybatis配置的数据源到当前线程中找资源,如果没有找到,提示没有注册SqlSessionSynchronization事务同步器
if (TransactionSynchronizationManager.getResource(environment.getDataSource()) == null) {
LOGGER.debug(() -> "SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");
}
// 如果找到了,抛出异常,SqlSessionFactory必须使用SpringManagedTransactionFactory才能使用Spring事务同步
else {
throw new TransientDataAccessResourceException("SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
}
}
} else {
LOGGER.debug(() -> "SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
}
}
// 关闭SqlSession
public static void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
// 获取当前线程中的SqlSession
SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
// 如果与给定的SqlSession是同一个,表示他们是同一个事务
if ((holder != null) && (holder.getSqlSession() == session)) {
LOGGER.debug(() -> "Releasing transactional SqlSession [" + session + "]");
// 将该SqlSession引用的数量-1
holder.released();
}
// 如果不是同一个,则直接关闭
else {
LOGGER.debug(() -> "Closing non transactional SqlSession [" + session + "]");
// 关闭SqlSession
session.close();
}
}
// 获取并校验SqlSession
private static SqlSession sessionHolder(ExecutorType executorType, SqlSessionHolder holder) {
SqlSession session = null;
// 如果当前线程存在SqlSession,并且与事务进行同步了
if (holder != null && holder.isSynchronizedWithTransaction()) {
// 保存的SqlSession的执行器类型与需要使用的执行器类型不一样,那么这个操作就无法继续,抛出异常
if (holder.getExecutorType() != executorType) {
throw new TransientDataAccessResourceException("Cannot change the ExecutorType when there is an existing transaction");
}
// 记录当前SqlSession被引用的次数
holder.requested();
LOGGER.debug(() -> "Fetched SqlSession [" + holder.getSqlSession() + "] from current transaction");
// 获取SqlSession对象
session = holder.getSqlSession();
}
return session;
}
// 是否是SqlSession事务
public static boolean isSqlSessionTransactional(SqlSession session, SqlSessionFactory sessionFactory) {
// 从当前线程中获取SqlSession
SqlSessionHolder holder = (SqlSessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
// 如果获取到,并且与给定的SqlSession是一同个,表示是指定SqlSession的事务
return (holder != null) && (holder.getSqlSession() == session);
}
}
// SqlSession的事务同步器,在处理事务的时候会根据生命周期进行同步执行
private static final class SqlSessionSynchronization implements TransactionSynchronization {
// SqlSession对象
private final SqlSessionHolder holder;
// SqlSessionFactory对象
private final SqlSessionFactory sessionFactory;
// SqlSession是否是活跃状态
private boolean holderActive = true;
public int getOrder() {
// 在任何连接同步之前的顺序
return DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 1;
}
// 事务暂停的时候执行的同步操作
@Override
public void suspend() {
// 如果SqlSession是活跃状态,不是活跃状态就不需要处理了
if (this.holderActive) {
LOGGER.debug(() -> "Transaction synchronization suspending SqlSession [" + this.holder.getSqlSession() + "]");
// 将SqlSession从当前线程解绑
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
}
}
// 从暂停到恢复
@Override
public void resume() {
// 如果SqlSession是活跃状态,不是活跃状态就不需要处理了
if (this.holderActive) {
// 将SqlSession重新绑定到当前线程中
LOGGER.debug(() -> "Transaction synchronization resuming SqlSession [" + this.holder.getSqlSession() + "]");
TransactionSynchronizationManager.bindResource(this.sessionFactory, this.holder);
}
}
// 事务提交之前要进行的同步操作
@Override
public void beforeCommit(boolean readOnly) {
// 事务是活跃状态
if (TransactionSynchronizationManager.isActualTransactionActive()) {
try {
LOGGER.debug(() -> "Transaction synchronization committing SqlSession [" + this.holder.getSqlSession() + "]");
// 执行SqlSession的提交方法
this.holder.getSqlSession().commit();
} catch (PersistenceException p) {
if (this.holder.getPersistenceExceptionTranslator() != null) {
// 将异常统一转换为DataAccessException
DataAccessException translated = this.holder.getPersistenceExceptionTranslator().translateExceptionIfPossible(p);
if (translated != null) {
throw translated;
}
}
throw p;
}
}
}
// 在事务完成之前的同步操作
@Override
public void beforeCompletion() {
// 现在关闭SqlSession并注销它
if (!this.holder.isOpen()) {
LOGGER.debug(() -> "Transaction synchronization deregistering SqlSession [" + this.holder.getSqlSession() + "]");
// 解绑线程的SqlSession
TransactionSynchronizationManager.unbindResource(sessionFactory);
// 标记为非活跃状态
this.holderActive = false;
LOGGER.debug(() -> "Transaction synchronization closing SqlSession [" + this.holder.getSqlSession() + "]");
// 关闭SqlSession
this.holder.getSqlSession().close();
}
}
// 事务完成之后的同步操作
@Override
public void afterCompletion(int status) {
// 活跃状态从需要处理
if (this.holderActive) {
LOGGER.debug(() -> "Transaction synchronization deregistering SqlSession [" + this.holder.getSqlSession() + "]");
// 将SqlSession进行解绑如果可以
TransactionSynchronizationManager.unbindResourceIfPossible(sessionFactory);
// 标记为非活跃状态
this.holderActive = false;
LOGGER.debug(() -> "Transaction synchronization closing SqlSession [" + this.holder.getSqlSession() + "]");
// 关闭SqlSession
this.holder.getSqlSession().close();
}
// 重置属性,清空引用次数
this.holder.reset();
}
}
// 创建Mapper接口Bean的FactoryBean对象
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
// Mapper接口类型
private Class<T> mapperInterface;
// 是否添加到Configuration配置类中
private boolean addToConfig = true;
public MapperFactoryBean(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
@Override
protected void checkDaoConfig() {
super.checkDaoConfig();
// 获取配置类
Configuration configuration = getSqlSession().getConfiguration();
// 按照配置将该Mapper添加到配置类中
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
configuration.addMapper(this.mapperInterface);
}
}
// 从SqlSesson中获取Mapper
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
@Override
public Class<T> getObjectType() {
return this.mapperInterface;
}
@Override
public boolean isSingleton() {
return true;
}
}
// 提供SqlSession的Dao支持的工具
public abstract class SqlSessionDaoSupport extends DaoSupport {
// SqlSession模板对象,就是一个SqlSession
private SqlSessionTemplate sqlSessionTemplate;
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
// 创建SqlSession对象
this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
}
}
// 如果需要创建不同的SqlSessionTemplate对象,可以重写
protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
public final SqlSessionFactory getSqlSessionFactory() {
return (this.sqlSessionTemplate != null ? this.sqlSessionTemplate.getSqlSessionFactory() : null);
}
public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
this.sqlSessionTemplate = sqlSessionTemplate;
}
public SqlSession getSqlSession() {
return this.sqlSessionTemplate;
}
public SqlSessionTemplate getSqlSessionTemplate() {
return this.sqlSessionTemplate;
}
@Override
protected void checkDaoConfig() {
notNull(this.sqlSessionTemplate, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
// Mapper接口扫描器
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
// 需要扫描的包
public String basePackage;
// 是否将Mapper添加到Mybatis的Configuration对象中,因为在Spring中,Mapper是交给Spring管理
public boolean addToConfig = true;
// 懒加载
public String lazyInitialization;
// SqlSession工厂
public SqlSessionFactory sqlSessionFactory;
// SqlSession会话
public SqlSessionTemplate sqlSessionTemplate;
// SqlSessionFactory的BeanName
public String sqlSessionFactoryBeanName;
// SqlSessionTemplate的BeanName
public String sqlSessionTemplateBeanName;
// 需要过滤的注解类型
public Class<? extends Annotation> annotationClass;
// 需要过滤的接口类型
public Class<?> markerInterface;
// 创建Mapper接口的MapperFactoryBean对象
public Class<? extends MapperFactoryBean> mapperFactoryBeanClass;
// Spring上下文
public ApplicationContext applicationContext;
// 当前Mapper扫描器的Bean的名称
public String beanName;
// 是否需要处理属性占位符
public boolean processPropertyPlaceHolders;
// beanName生成器
public BeanNameGenerator nameGenerator;
// Mapper默认的作用域
public String defaultScope;
// 解析注册Mapper的BeanDefinition信息
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 如果需要处理属性占位符
if (this.processPropertyPlaceHolders) {
// 处理属性中的占位符
this.processPropertyPlaceHolders();
}
// 创建类路径下的Mapper扫描器
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
// 将属性设置到扫描器中
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
if (StringUtils.hasText(lazyInitialization)) {
scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization));
}
if (StringUtils.hasText(defaultScope)) {
scanner.setDefaultScope(defaultScope);
}
// 注册扫描过滤器
scanner.registerFilters();
// 开始扫描所有包
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
/*
* 执行属性的占位符替换,PropertyResourceConfigurer是对系统属性进行配置的一个接口
* 因为BeanDefinitionRegistryPostProcessor在BeanFactoryPostProcessors之前被调用
* 这意味着PropertyResourceConfigurer再该类中不会被加载生效,为了避免这种情况,找到在上下文中定义的PropertyResourceConfigurer
* 在当前类运行,然后更新这些属性值。
*/
public void processPropertyPlaceHolders() {
// 从Spring容器中获取PropertyResourceConfigurer属性资源配置类
Map<String, PropertyResourceConfigurer> prcs = applicationContext.getBeansOfType(PropertyResourceConfigurer.class, false, false);
// 如果存在配置类
if (!prcs.isEmpty() && applicationContext instanceof ConfigurableApplicationContext) {
// 获取当前MapperScannerConfigurer的BeanDefinition信息
BeanDefinition mapperScannerBean = ((ConfigurableApplicationContext) applicationContext).getBeanFactory().getBeanDefinition(beanName);
// 创建一个默认的Bean工厂
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
// 将当前MapperScannerConfigurer的Bean注册到创建的新工厂中
factory.registerBeanDefinition(beanName, mapperScannerBean);
// 执行所有PropertyResourceConfigurer
for (PropertyResourceConfigurer prc : prcs.values()) {
// 将mapperScannerBean中的属性进行解析占位符,该配置类会对BeanFactory中所有的BeanDefinition中设置的属性处理占位符
prc.postProcessBeanFactory(factory);
}
// 获取到解析占位符之后的信息
PropertyValues values = mapperScannerBean.getPropertyValues();
// 将最终替换了占位符的结果替换之前有占位符的数据
this.basePackage = getPropertyValue("basePackage", values);
this.sqlSessionFactoryBeanName = getPropertyValue("sqlSessionFactoryBeanName", values);
this.sqlSessionTemplateBeanName = getPropertyValue("sqlSessionTemplateBeanName", values);
this.lazyInitialization = getPropertyValue("lazyInitialization", values);
this.defaultScope = getPropertyValue("defaultScope", values);
}
// 单独将属性再进行一遍占位符替换
this.basePackage = Optional.ofNullable(this.basePackage).map(getEnvironment()::resolvePlaceholders).orElse(null);
this.sqlSessionFactoryBeanName = Optional.ofNullable(this.sqlSessionFactoryBeanName).map(getEnvironment()::resolvePlaceholders).orElse(null);
this.sqlSessionTemplateBeanName = Optional.ofNullable(this.sqlSessionTemplateBeanName).map(getEnvironment()::resolvePlaceholders).orElse(null);
this.lazyInitialization = Optional.ofNullable(this.lazyInitialization).map(getEnvironment()::resolvePlaceholders).orElse(null);
this.defaultScope = Optional.ofNullable(this.defaultScope).map(getEnvironment()::resolvePlaceholders).orElse(null);
}
}
// Mapper接口的类扫描器
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner {
static final String FACTORY_BEAN_OBJECT_TYPE = "factoryBeanObjectType";
// 是否将Mapper添加到Mybatis的Configuration对象中,因为在Spring中,Mapper是交给Spring管理
private boolean addToConfig = true;
// 懒加载
private boolean lazyInitialization;
// 如果没有找到Mapper,打印警告日志
private boolean printWarnLogIfNotFoundMappers = true;
// SqlSession工厂
private SqlSessionFactory sqlSessionFactory;
// SqlSession会话
private SqlSessionTemplate sqlSessionTemplate;
// SqlSessionFactory的BeanName
private String sqlSessionTemplateBeanName;
// SqlSessionTemplate的BeanName
private String sqlSessionFactoryBeanName;
// 需要过滤的注解类型
private Class<? extends Annotation> annotationClass;
// 需要过滤的接口类型
private Class<?> markerInterface;
// 创建Mapper接口的MapperFactoryBean对象
private Class<? extends MapperFactoryBean> mapperFactoryBeanClass = MapperFactoryBean.class;
// Mapper默认的作用域
private String defaultScope;
public ClassPathMapperScanner(BeanDefinitionRegistry registry) {
super(registry, false);
setIncludeAnnotationConfig(!AotDetector.useGeneratedArtifacts());
setPrintWarnLogIfNotFoundMappers(!NativeDetector.inNativeImage());
}
// 注册扫描过滤器
public void registerFilters() {
// 默认扫描所有接口
boolean acceptAllInterfaces = true;
// 是否指定了需要过滤的接口或者注解,如果设置了,就需要添加对应的注解或者接口过滤器
if (this.annotationClass != null) {
addIncludeFilter(new AnnotationTypeFilter(this.annotationClass));
acceptAllInterfaces = false;
}
// 如果指定了过滤接口
if (this.markerInterface != null) {
// 添加过滤器
addIncludeFilter(new AssignableTypeFilter(this.markerInterface) {
// 不匹配类名,只匹配接口
@Override
protected boolean matchClassName(String className) {
return false;
}
});
acceptAllInterfaces = false;
}
// 如果接受扫描所有接口,添加一个不受约束的扫描器
if (acceptAllInterfaces) {
// 默认包含过滤器接受所有类
addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
}
// 排除package-info的过滤器
addExcludeFilter((metadataReader, metadataReaderFactory) -> {
String className = metadataReader.getClassMetadata().getClassName();
return className.endsWith("package-info");
});
}
// 重新默认的扫描逻辑
@Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 调用父类的扫描方法,将所有符合条件的Mapper扫描出来
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
// 如果不存在任何符合条件的Mapper
if (beanDefinitions.isEmpty()) {
// 打印日志
if (printWarnLogIfNotFoundMappers) {
LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
}
} else {
// 对这些扫描的Mapper进行加工,设置为MapperFactoryBean
processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}
// 对这些扫描的Mapper进行加工,设置为MapperFactoryBean
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
AbstractBeanDefinition definition;
BeanDefinitionRegistry registry = getRegistry();
// 遍历所有的Mapper的BeanDefinition
for (BeanDefinitionHolder holder : beanDefinitions) {
definition = (AbstractBeanDefinition) holder.getBeanDefinition();
boolean scopedProxy = false;
// 是否需要进行作用域代理
if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) {
definition = (AbstractBeanDefinition) Optional
.ofNullable(((RootBeanDefinition) definition).getDecoratedDefinition())
.map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> new IllegalStateException("The target bean definition of scoped proxy bean not found. Root bean definition[" + holder + "]"));
// 标记该Mapper需要进行作用域代理
scopedProxy = true;
}
String beanClassName = definition.getBeanClassName();
LOGGER.debug(() -> "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface");
// 添加构造参数Mapper接口类型
definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); // issue #59
// 设置mapperInterface属性
definition.getPropertyValues().add("mapperInterface", Resources.classForName(beanClassName));
// 设置创建Mapper接口的FactoryBean
definition.setBeanClass(this.mapperFactoryBeanClass);
// 设置属性
definition.getPropertyValues().add("addToConfig", this.addToConfig);
// Mockito后处理器
definition.setAttribute(FACTORY_BEAN_OBJECT_TYPE, beanClassName);
boolean explicitFactoryUsed = false;
// 设置sqlSessionFactory
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
// 不能同时使用:sqlSessionTemplate和sqlSessionFactory。sqlSessionFactory被忽略
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
LOGGER.warn(() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
LOGGER.warn(() -> "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
// 如果上面条件都不满足,只能通过ByType的注入方式,从Spring容器中找Bean对象
if (!explicitFactoryUsed) {
LOGGER.debug(() -> "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
// 设置懒加载
definition.setLazyInit(lazyInitialization);
// 如果已经是作用域代理了,就不往下走
// 因为下面在处理作用域代理的情况,当前Mapper的BeanDefinition已经在容器中,所以不需要注册该Mapper的BeanDefinition,只需要修改属性就行
if (scopedProxy) {
continue;
}
// 设置Bean指定的作用域
if (ConfigurableBeanFactory.SCOPE_SINGLETON.equals(definition.getScope()) && defaultScope != null) {
definition.setScope(defaultScope);
}
// 如果设置了Mapper不是单例
if (!definition.isSingleton()) {
// 创建Mapper的作用域代理
BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true);
if (registry.containsBeanDefinition(proxyHolder.getBeanName())) {
registry.removeBeanDefinition(proxyHolder.getBeanName());
}
// 注册该Mapper的作用域代理对象
registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition());
}
}
}
// Mapper必须符合是独立的接口才会被扫描
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
}
// 就为了打印一点日志
@Override
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) {
if (super.checkCandidate(beanName, beanDefinition)) {
return true;
} else {
LOGGER.warn(() -> "Skipping MapperFactoryBean with name '" + beanName + "' and '" + beanDefinition.getBeanClassName() + "' mapperInterface" + ". Bean already defined with the same name!");
return false;
}
}
}
// 创建SqlSession的FactoryBean
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ContextRefreshedEvent> {
// 正则路径资源解析器
private static final ResourcePatternResolver RESOURCE_PATTERN_RESOLVER = new PathMatchingResourcePatternResolver();
private static final MetadataReaderFactory METADATA_READER_FACTORY = new CachingMetadataReaderFactory();
// mybatis配置类路径
private Resource configLocation;
// Mybatis的配置类对象
private Configuration configuration;
// 所有Mapper.xml的路径
private Resource[] mapperLocations;
// 数据源
private DataSource dataSource;
// Mybatis的事务工厂
private TransactionFactory transactionFactory;
// Mybatis的全局属性配置
private Properties configurationProperties;
// Mybatis创建SqlSessionFactory的Builder对象
private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 需要创建的SqlSessionFactory对象
private SqlSessionFactory sqlSessionFactory;
// Mybatis的环境名称
private String environment = SqlSessionFactoryBean.class.getSimpleName();
// 当mybatis的映射语句没有解析完成是否需要快速失败
private boolean failFast;
// mybatis插件
private Interceptor[] plugins;
// mybatis类型转换器
private TypeHandler<?>[] typeHandlers;
// mybatis类型转换器包名
private String typeHandlersPackage;
// 默认的枚举类型转换器
private Class<? extends TypeHandler> defaultEnumTypeHandler;
// 类型别名
private Class<?>[] typeAliases;
// 别名的包名
private String typeAliasesPackage;
// 指定筛选指定类的别名
private Class<?> typeAliasesSuperType;
// SQL脚本解析器
private LanguageDriver[] scriptingLanguageDrivers;
// 默认的SQL脚本解析器
private Class<? extends LanguageDriver> defaultScriptingLanguageDriver;
// 数据库ID提供商
private DatabaseIdProvider databaseIdProvider;
// 1. SpringBootVFS 是 MyBatis 在 Spring Boot 中使用的虚拟文件系统(Virtual File System)
// 2. 它允许 MyBatis 在 Spring Boot 打包的jar中查找和加载 XML 映射文件。
private Class<? extends VFS> vfs;
// Mybatis的缓存对象
private Cache cache;
// Mybatis的对象工厂
private ObjectFactory objectFactory;
// Mybatis的对象包装器工厂
private ObjectWrapperFactory objectWrapperFactory;
// 设置数据源
public void setDataSource(DataSource dataSource) {
if (dataSource instanceof TransactionAwareDataSourceProxy) {
this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
} else {
this.dataSource = dataSource;
}
}
@Override
public void afterPropertiesSet() throws Exception {
// 初始化SqlSessionFactory
this.sqlSessionFactory = buildSqlSessionFactory();
}
// 构建SqlSessionFactory对象
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
// 最终的Mybatis的Configuration对象
final Configuration targetConfiguration;
// mybatis的xml配置文件解析器
XMLConfigBuilder xmlConfigBuilder = null;
// 如果给当前FactoryBean设置了配置类
if (this.configuration != null) {
targetConfiguration = this.configuration;
// 设置全局属性
if (targetConfiguration.getVariables() == null) {
targetConfiguration.setVariables(this.configurationProperties);
} else if (this.configurationProperties != null) {
targetConfiguration.getVariables().putAll(this.configurationProperties);
}
}
// 如果没有设置Configuration对象,但是给定了Mybatis-config配置文件
else if (this.configLocation != null) {
// 使用XML配置文件解析器解析该配置
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
// 此时创建的是一个默认的Configuration对象,并没用解析该配置文件,因为要以配置文件中的配置为最终版本
// 说白了就是存在相同配置,会将配置文件中的配置覆盖在Spring中设置的配置
targetConfiguration = xmlConfigBuilder.getConfiguration();
}
// 其他情况,创建默认的配置对象
else {
LOGGER.debug(() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
targetConfiguration = new Configuration();
// 如果存在全局属性,设置全局属性
Optional.ofNullable(this.configurationProperties).ifPresent(targetConfiguration::setVariables);
}
// 将当前对象中的属性全部设置的Configuration对象中
Optional.ofNullable(this.objectFactory).ifPresent(targetConfiguration::setObjectFactory);
Optional.ofNullable(this.objectWrapperFactory).ifPresent(targetConfiguration::setObjectWrapperFactory);
Optional.ofNullable(this.vfs).ifPresent(targetConfiguration::setVfsImpl);
// 注册别名的包名
if (hasLength(this.typeAliasesPackage)) {
scanClasses(this.typeAliasesPackage, this.typeAliasesSuperType).stream()
.filter(clazz -> !clazz.isAnonymousClass()).filter(clazz -> !clazz.isInterface())
.filter(clazz -> !clazz.isMemberClass()).forEach(targetConfiguration.getTypeAliasRegistry()::registerAlias);
}
// 注册别名的类名
if (!isEmpty(this.typeAliases)) {
Stream.of(this.typeAliases).forEach(typeAlias -> {
targetConfiguration.getTypeAliasRegistry().registerAlias(typeAlias);
LOGGER.debug(() -> "Registered type alias: '" + typeAlias + "'");
});
}
// 注册插件拦截器
if (!isEmpty(this.plugins)) {
Stream.of(this.plugins).forEach(plugin -> {
targetConfiguration.addInterceptor(plugin);
LOGGER.debug(() -> "Registered plugin: '" + plugin + "'");
});
}
// 添加类型转换器的包名
if (hasLength(this.typeHandlersPackage)) {
scanClasses(this.typeHandlersPackage, TypeHandler.class).stream().filter(clazz -> !clazz.isAnonymousClass())
.filter(clazz -> !clazz.isInterface()).filter(clazz -> !Modifier.isAbstract(clazz.getModifiers()))
.forEach(targetConfiguration.getTypeHandlerRegistry()::register);
}
// 添加类型转换器
if (!isEmpty(this.typeHandlers)) {
Stream.of(this.typeHandlers).forEach(typeHandler -> {
targetConfiguration.getTypeHandlerRegistry().register(typeHandler);
LOGGER.debug(() -> "Registered type handler: '" + typeHandler + "'");
});
}
// 设置默认的枚举处理器
targetConfiguration.setDefaultEnumTypeHandler(defaultEnumTypeHandler);
// 设置SQL脚本解析器
if (!isEmpty(this.scriptingLanguageDrivers)) {
Stream.of(this.scriptingLanguageDrivers).forEach(languageDriver -> {
targetConfiguration.getLanguageRegistry().register(languageDriver);
LOGGER.debug(() -> "Registered scripting language driver: '" + languageDriver + "'");
});
}
Optional.ofNullable(this.defaultScriptingLanguageDriver).ifPresent(targetConfiguration::setDefaultScriptingLanguage);
// 设置数据库ID
if (this.databaseIdProvider != null) {
try {
targetConfiguration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
} catch (SQLException e) {
throw new IOException("Failed getting a databaseId", e);
}
}
// 添加缓存
Optional.ofNullable(this.cache).ifPresent(targetConfiguration::addCache);
// 如果使用是mybatis-config配置文件
if (xmlConfigBuilder != null) {
try {
// 开始解析该配置文件,确保以mybatis配置文件的属性为准
xmlConfigBuilder.parse();
LOGGER.debug(() -> "Parsed configuration file: '" + this.configLocation + "'");
} catch (Exception ex) {
throw new IOException("Failed to parse config resource: " + this.configLocation, ex);
} finally {
ErrorContext.instance().reset();
}
}
// 设置环境对象
targetConfiguration.setEnvironment(new Environment(this.environment, this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory, this.dataSource));
// 如果mapper.xml路径不为空
if (this.mapperLocations != null) {
// 没扫描到mapper.xml
if (this.mapperLocations.length == 0) {
LOGGER.warn(() -> "Property 'mapperLocations' was specified but matching resources are not found.");
}
// 如果扫描到mapper.xml
else {
// 遍历所有的mapper.xml
for (Resource mapperLocation : this.mapperLocations) {
if (mapperLocation == null) {
continue;
}
try {
// 使用mapper.xml解析器对mapper进行解析
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new IOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
}
LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'");
}
}
} else {
LOGGER.debug(() -> "Property 'mapperLocations' was not specified.");
}
// 开始构建SqlSessionFactory对象
return this.sqlSessionFactoryBuilder.build(targetConfiguration);
}
// 获取sqlSessionFactory对象
@Override
public SqlSessionFactory getObject() throws Exception {
// 如果不存在,手动初始化创建对象
if (this.sqlSessionFactory == null) {
this.afterPropertiesSet();
}
return this.sqlSessionFactory;
}
@Override
public Class<? extends SqlSessionFactory> getObjectType() {
return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
}
@Override
public boolean isSingleton() {
return true;
}
// 容器刷新完成之后,将所有映射语句最后加载一遍,如果还未能加载成功,抛出异常
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (failFast) {
// 快速失败->检查所有语句是否解析完成,如果没有,抛出异常
this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
}
}
// 扫描类
private Set<Class<?>> scanClasses(String packagePatterns, Class<?> assignableType) throws IOException {
Set<Class<?>> classes = new HashSet<>();
// 使用","分割包名
String[] packagePatternArray = tokenizeToStringArray(packagePatterns, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// 遍历所有的包名
for (String packagePattern : packagePatternArray) {
// 按照路径表达式找到所有的资源
Resource[] resources = RESOURCE_PATTERN_RESOLVER.getResources(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(packagePattern) + "/**/*.class");
// 遍历所有的资源
for (Resource resource : resources) {
try {
// 解析类的元数据信息
ClassMetadata classMetadata = METADATA_READER_FACTORY.getMetadataReader(resource).getClassMetadata();
Class<?> clazz = Resources.classForName(classMetadata.getClassName());
// 如果符合给定的类型,则保留该扫描的类
if (assignableType == null || assignableType.isAssignableFrom(clazz)) {
classes.add(clazz);
}
} catch (Throwable e) {
LOGGER.warn(() -> "Cannot load the '" + resource + "'. Cause by " + e.toString());
}
}
}
return classes;
}
}
01-11
344

12-10
2000
