首先我们来看MapperScannerConfigurer的继承和实现关系
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware
这里我们关注BeanDefinitionRegistryPostProcessor这个接口:它继承了BeanFactoryPostProcessor,用来在BeanFactoryPostProcessor初始化之前再往容器中注册一些额外的BeanDefinition。
看到这里你应该有点想法了吧?对,它就是扫描了我们给的basePackage下的类之后,然后生成BeanDefinition再添加到容器中的。
下面还是从源码入手,我们先看BeanDefinitionRegistryPostProcessor初始化时调用的方法:
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
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.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
这里我们先看ClassPathMapperScanner这个类,可以从名字上(Scanner)看出来,它就是去Scan的核心类。并且除了最后一行,其余的代码都是在配置这个Scanner。
这里根据名字我们可以猜想,最后一行scanner.scan(...)就是在扫描Mapper并将它添加到BeanDefinition中去。为了验证我们的想法,跟进去看看:
public int scan(String... basePackages) {
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
doScan(basePackages);
// Register annotation config processors, if necessary.
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
}
发现进的并不是ClassPathMapperScanner这个类,而是ClassPathBeanDefinitionScanner这个类,并且ClassPathBeanDefinitionScanner在spring的包下。那么再回过头来看看ClassPathBeanDefinitionScanner的定义:
public class ClassPathMapperScanner extends ClassPathBeanDefinitionScanner
恩,确实是继承了org.springframework.context.annotation.ClassPathBeanDefinitionScanner,并且我们可以看到它覆盖了好几个方法:

doScan(...),熟吗?不熟的请往上看到scan方法中。监测的逻辑实际上都在doScan(...)中,接下来我们就关注这个Override的方法:
@Override public SetdoScan(String... basePackages) { Set beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) { logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration."); } else { for (BeanDefinitionHolder holder : beanDefinitions) { GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition(); if (logger.isDebugEnabled()) { logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition.getBeanClassName() + "' mapperInterface"); } // the mapper interface is the original class of the bean // but, the actual class of the bean is MapperFactoryBean definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName