Mybatis整合SpringBoot源码解析

@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 {
 *
 *   &#064;Bean
 *   public DataSource dataSource() {
 *     // 自动初始化脚本
 *     return new EmbeddedDatabaseBuilder().addScript("schema.sql").build();
 *   }
 *
 *   &#064;Bean
 *   public DataSourceTransactionManager transactionManager() {
 *     return new DataSourceTransactionManager(dataSource());
 *   }
 *
 *   &#064;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;
    }

}

【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zip 基于SpringBoot+MyBatis+Redis的图像素材管理系统源码(高分毕设).zi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值