Mybatis3源码笔记(八)小窥MyBatis-plus (3)

Mybatis3源码笔记(八)小窥MyBatis-plus

Mybatis3源码笔记(八)小窥MyBatis-plus

当时就懵逼了,mapper接口是怎么变成MapperFactoryBean,FactoryBean用来spring里用来bean封装这一套我们是理解的,关键是我们的mapper接口在哪进行转换的呢?

首先分析下我们的Mapper接口是怎么被发现的?这么一想,我就立刻想到了在启动类上的@MapperScan(basePackages = {"com.xx.dao"}),这个@MapperScan注解就是扫描对应包下面的mapper进行注册的。

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

打开我们就发现了MapperScannerRegistrar类,它实现了ImportBeanDefinitionRegistrar接口,在registerBeanDefinitions方法中进行手动注册bean的操作

Mybatis3源码笔记(八)小窥MyBatis-plus

void registerBeanDefinitions(AnnotationMetadata annoMeta, AnnotationAttributes annoAttrs, BeanDefinitionRegistry registry, String beanName) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); builder.addPropertyValue("processPropertyPlaceHolders", true); ... ... builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(basePackages)); registry.registerBeanDefinition(beanName, builder.getBeanDefinition()); } 终于找到了根源了: MapperScannerConfigurer。

Mybatis3源码笔记(八)小窥MyBatis-plus

我们看下这个类的注释:BeanDefinitionRegistryPostProcessor从基包开始递归搜索接口,并将其注册为MapperFactoryBean 。 请注意,只有具有至少一种方法的接口才会被注册; 具体的类将被忽略。

从上面这段话,我们就大致知道他的作用,他实现了BeanDefinitionRegistryPostProcessor接口,在postProcessBeanDefinitionRegistry里对所有的package下扫描到的未实例但已注册的bean进行封装处理。具体我们看下代码:

@Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 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.setMapperFactoryBeanClass(this.mapperFactoryBeanClass); if (StringUtils.hasText(lazyInitialization)) { scanner.setLazyInitialization(Boolean.valueOf(lazyInitialization)); } scanner.registerFilters(); scanner.scan( StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }

postProcessBeanDefinitionRegistry 方法里注册了一个ClassPathBeanDefinitionScanner,一个扫描器。它通过basePackage, annotationClass或markerInterface注册markerInterface 。 如果指定了annotationClass和/或markerInterface ,则仅搜索指定的类型(将禁用搜索所有接口)。作用很明显了,在我们这的作用就是通过basePackage来扫描包内的所有mapperbeans。

最后一步的scan操作,我们来看下操作。

Mybatis3源码笔记(八)小窥MyBatis-plus

最终再说下所有mapper注入的地方,在ServiceImpl里:

Mybatis3源码笔记(八)小窥MyBatis-plus

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjgfp.html