Mybatis的原理分析1(@Mapper是如何生效的)

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

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

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

 1   public static class AutoConfiguredMapperScannerRegistrar
 2       implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
 3 
 4     private BeanFactory beanFactory;
 5 
 6     private ResourceLoader resourceLoader;
 7 
 8     @Override
 9     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
10 
11       logger.debug("Searching for mappers annotated with @Mapper");
12 
13       ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
14 
15       try {
16         if (this.resourceLoader != null) {
17           scanner.setResourceLoader(this.resourceLoader);
18         }
19 
20         List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
21         if (logger.isDebugEnabled()) {
22           for (String pkg : packages) {
23             logger.debug("Using auto-configuration base package '{}'", pkg);
24           }
25         }
26 
27         scanner.setAnnotationClass(Mapper.class);
28         scanner.registerFilters();
29         scanner.doScan(StringUtils.toStringArray(packages));
30       } catch (IllegalStateException ex) {
31         logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
32       }
33     }

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

 1   @Override
 2   public Set<BeanDefinitionHolder> doScan(String... basePackages) {
 3     Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
 4 
 5     if (beanDefinitions.isEmpty()) {
 6       logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
 7     } else {
 8       processBeanDefinitions(beanDefinitions);
 9     }
10 
11     return beanDefinitions;
12   }

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

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

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

 

posted @ 2019-10-24 14:56  李斯特王  Views(1702)  Comments(0Edit  收藏  举报