NOTE

MyBatis Auto-Configuration

How Spring Boot enables MyBatis auto-configuration and how AutoConfiguredMapperScannerRegistrar determines which package to scan for @Mapper interfaces.

JavaCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Enable MyBatis Auto-Configuration

Spring Boot auto-configures MyBatis through MybatisAutoConfiguration, as follows:

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
 @Override
  public void afterPropertiesSet() {
    // If configuration-file validation is enabled, check whether the configuration file exists
    // It is disabled by default
    checkConfigFileExists();
  }
}

It implements InitializingBean. After Spring instantiates the MybatisAutoConfiguration bean, it calls its afterPropertiesSet method, which checks whether the mybatis.config configuration file exists.

In addition, there is another @Configuration class at the bottom of this class:

@org.springframework.context.annotation.Configuration
@Import({ AutoConfiguredMapperScannerRegistrar.class })// Imports AutoConfiguredMapperScannerRegistrar
@ConditionalOnMissingBean(MapperFactoryBean.class)
public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
      logger.debug("No {} found.", MapperFactoryBean.class.getName());
    }
}

The purpose of this class is to import AutoConfiguredMapperScannerRegistrar. We continue by studying it.

2. How Is the Package to Scan Determined?

AutoConfiguredMapperScannerRegistrar starts scanning from the package of @MybatisAutoConfiguration, and adds all classes annotated with @Mapper to the container.

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

  if (!AutoConfigurationPackages.has(this.beanFactory)) {
    logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
    return;
  }

  logger.debug("Searching for mappers annotated with @Mapper");

    // packages is the package where MybatisAutoConfiguration is located: com.zsk.template
  List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
  if (logger.isDebugEnabled()) {
    packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
  }

  ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
  if (this.resourceLoader != null) {
    scanner.setResourceLoader(this.resourceLoader);
  }
  // Scan all classes annotated with @Mapper
  scanner.setAnnotationClass(Mapper.class);
  scanner.registerFilters();
  scanner.doScan(StringUtils.toStringArray(packages));

}

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub