接着我们上次说的SpringBoot自动加载原理。我们大概明白了在maven中引入mybatis后,这个模块是如下加载的。

  可能会有人问了,一般我们的dao层都是通过Mapper接口+Mapper.xml的方式来操作数据库的,但是@Mapper注解并不是SpringBoot自带的注解,为什么加上@Mapper注解后这个接口就能够在项目中被各处注入使用了呢?

  1:我们在maven中引入mybatis后就会自动加载 MybatisAutoConfiguration 这个类,它包含一个内部类 AutoConfiguredMapperScannerRegistrar,我们可以查看这个类的源码,部分如下:

   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);
}
}

  我们会看到有个 registerBeanDefinitions() 方法。没错,这个方法就是那些被@Mapper标记的接口能被注入到SpringBoot的BeanFactory的关键。我们阅读这个方法,会发现有个 scanner.doScan(StringUtils.toStringArray(packages)),它是干嘛的,我们跳进去看一下,部分代码如下:

   @Override
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); if (beanDefinitions.isEmpty()) {
logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
processBeanDefinitions(beanDefinitions);
} return beanDefinitions;
}

  这个doScan方法调用了父类ClassPathBeanDefinitionScanner的doScan方法。这个类是Bean被注入BeanFactory的关键类,doScan方法是其中的关键方法,这里就不再分析。

  那么通过这块,我们得到了哪些呢?

  1:@Mapper注解的类是如何被注入到ApplicationContext(或者BeanFactory)里的

05-23 02:45