zoukankan      html  css  js  c++  java
  • SpringBoot源码分析(三)整合MyBatis

    一、前言

    ​ SpringBoot中是没有MyBatis的,可以通过在使用SpringBoot时如果我们要用MyBatis的话,需要相比普通引用MyBatis需要多做哪些工作?来反推出整合自动配置的原理

    二、对比SpringBoot中使用MyBatis区别

    1.pom方面

    相比平时不一样的是,引用的是starter:

    <dependency>
    		<groupId>org.mybatis.spring.boot</groupId>
    		<artifactId>mybatis-spring-boot-starter</artifactId>
    		<version>1.3.2</version>
    </dependency>  
    

    2.注解

    在启动类打上了@MapperScan("top.yejian123.springbootM.mapper")

    3.配置文件

    application.properties

    # Mybatis相关配置
    mybatis:
        #核心配置文件路径
        config-location: classpath:mybatis/mybatis-config.xml
        #映射配置文件路径
        mapper-locations: classpath:mybatis/mapper/*.xml
    

    三、逐个分析

    3.1 跟进打开pom:

    <dependencies>
        <!--SpringBoot-->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!--autoconfigure-->
        <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-autoconfigure</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
        </dependency>
        <!--mybatis-spring整合-->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
        </dependency>
    </dependencies>
    

    引入了一堆依赖,实际上看下来,相比以前新花样只有mybatis-spring-boot-autoconfigure

    打开这个jar包看:

    mybatis-spring-boot-autoconfigure

    就四个文件,看到了MybatisProperties,源码:

    @ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
    public class MybatisProperties {
    
      public static final String MYBATIS_PREFIX = "mybatis";
      
      //省略以下代码
    
    }	
    

    看到了@ConfigurationProperties,这也理解 application.properties 里配置的东西了,在这处理的

    3.2 @MapperScan("com.**.mapper")

    打开源码:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Documented
    @Import(MapperScannerRegistrar.class)
    public @interface MapperScan {
    	//...
    }
    

    导入了MapperScannerRegistrar,是spring和mybatis整合的时候扫描注册用的,监听相关事件通知完成扫描Mapper注册

    最终会发现主要是mybatis-spring-boot-autoconfigure,核心类是MybatisAutoConfiguration

    四、MybatisAutoConfiguration

    查看源码

    package org.mybatis.spring.boot.autoconfigure;
    
    @org.springframework.context.annotation.Configuration
    @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
    @ConditionalOnBean(DataSource.class)
    @EnableConfigurationProperties(MybatisProperties.class)
    @AutoConfigureAfter(DataSourceAutoConfiguration.class)
    public class MybatisAutoConfiguration {
    
      private final MybatisProperties properties;
    
      private final Interceptor[] interceptors;
    
      private final ResourceLoader resourceLoader;
    
      private final DatabaseIdProvider databaseIdProvider;
    
      private final List<ConfigurationCustomizer> configurationCustomizers;
    
      public MybatisAutoConfiguration(MybatisProperties properties,
                                      ObjectProvider<Interceptor[]> interceptorsProvider,
                                      ResourceLoader resourceLoader,
                                      ObjectProvider<DatabaseIdProvider> databaseIdProvider,
                                      ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
        this.properties = properties;
        this.interceptors = interceptorsProvider.getIfAvailable();
        this.resourceLoader = resourceLoader;
        this.databaseIdProvider = databaseIdProvider.getIfAvailable();
        this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
      }
    
      @PostConstruct
      public void checkConfigFileExists() {
        if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
          Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
          Assert.state(resource.exists(), "Cannot find config location: " + resource
              + " (please add config file or check your Mybatis configuration)");
        }
      }
    
      @Bean
      @ConditionalOnMissingBean
      public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        factory.setVfs(SpringBootVFS.class);
        if (StringUtils.hasText(this.properties.getConfigLocation())) {
          factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
        }
        Configuration configuration = this.properties.getConfiguration();
        if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
          configuration = new Configuration();
        }
        if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
          for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
            customizer.customize(configuration);
          }
        }
        factory.setConfiguration(configuration);
        if (this.properties.getConfigurationProperties() != null) {
          factory.setConfigurationProperties(this.properties.getConfigurationProperties());
        }
        if (!ObjectUtils.isEmpty(this.interceptors)) {
          factory.setPlugins(this.interceptors);
        }
        if (this.databaseIdProvider != null) {
          factory.setDatabaseIdProvider(this.databaseIdProvider);
        }
        if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
          factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
        }
        if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
          factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
        }
        if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
          factory.setMapperLocations(this.properties.resolveMapperLocations());
        }
    
        return factory.getObject();
      }
    
      @Bean
      @ConditionalOnMissingBean
      public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        ExecutorType executorType = this.properties.getExecutorType();
        if (executorType != null) {
          return new SqlSessionTemplate(sqlSessionFactory, executorType);
        } else {
          return new SqlSessionTemplate(sqlSessionFactory);
        }
      }
    
      public static class AutoConfiguredMapperScannerRegistrar
          implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
    
        private BeanFactory beanFactory;
    
        private ResourceLoader resourceLoader;
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
          logger.debug("Searching for mappers annotated with @Mapper");
    
          ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    
          try {
            if (this.resourceLoader != null) {
              scanner.setResourceLoader(this.resourceLoader);
            }
    
            List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
            if (logger.isDebugEnabled()) {
              for (String pkg : packages) {
                logger.debug("Using auto-configuration base package '{}'", pkg);
              }
            }
    
            scanner.setAnnotationClass(Mapper.class);
            scanner.registerFilters();
            scanner.doScan(StringUtils.toStringArray(packages));
          } catch (IllegalStateException ex) {
            logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
          }
        }
    
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
          this.beanFactory = beanFactory;
        }
    
        @Override
        public void setResourceLoader(ResourceLoader resourceLoader) {
          this.resourceLoader = resourceLoader;
        }
      }
    
      @org.springframework.context.annotation.Configuration
      @Import({ AutoConfiguredMapperScannerRegistrar.class })
      @ConditionalOnMissingBean(MapperFactoryBean.class)
      public static class MapperScannerRegistrarNotFoundConfiguration {
    
        @PostConstruct
        public void afterPropertiesSet() {
          logger.debug("No {} found.", MapperFactoryBean.class.getName());
        }
      }
    
    }
    
    

    会发现,

    ① : 导入了SqlSessionFactory
    ②:导入了sqlSessionTemplate
    ③:导入了mapperScanner

    Spring Boot启动时,会去实例化jar包mybatis-spring-boot-autoconfigure-starter中MybatisAutoConfiguration中的配置bean,包括SqlSessionFactory、SqlSessionTemplate。流程图如下:

    img

  • 相关阅读:
    AIMS 2013中的性能报告工具不能运行的解决办法
    读懂AIMS 2013中的性能分析报告
    在线研讨会网络视频讲座 方案设计利器Autodesk Infrastructure Modeler 2013
    Using New Profiling API to Analyze Performance of AIMS 2013
    Map 3D 2013 新功能和新API WebCast视频下载
    为Autodesk Infrastructure Map Server(AIMS) Mobile Viewer创建自定义控件
    ADN新开了云计算Cloud和移动计算Mobile相关技术的博客
    JavaScript修改css样式style
    文本编辑神器awk
    jquery 开发总结1
  • 原文地址:https://www.cnblogs.com/chz-blogs/p/13270200.html
Copyright © 2011-2022 走看看