首页 > 编程知识 正文

mapperscan注解失效,apimodelproperty注解

时间:2023-05-04 02:01:37 阅读:28415 作者:1581

@Mapper评论和@MapperScan评论是我们使用mybatis-spring的一般性评论,以前为了探索两个评论的关联性,我读了百度的文章,把@Mapper评论和@MapperScan评论翻译成干脆,自己把我的mybatis-spring和spring-boot的源代码分析结合起来,探索两个评论的关联性。

整篇文章以MapperScannerRegistrar、MybatisAutoConfiguration、autoconfiguredmapperscannerregistrar三个类为核心类进行了分析。

结论已经发表在文章的底部。

另一方面,启动类定义MapperScan注释的方式1、入口必须从@MapperScan注释说起

@MapperScan注释的内容显示,当SpringBoot主类定义MapperScan注释时,MapperScannerRegistrar类将BeanDefinition作为SpringBoot的BeanDefinition 感兴趣的人可以看到SpringBoot加载了BeanDefinitionRegistry和BeanDefinitionRegistry并实例化了Bean的源代码。

2 )观察实现ImportBeanDefinitionRegistrar接口的MapperScannerRegistrar类,在中, 在SpringBoot刷新上下文的invokebeandefinitionregistrypostprocessors方法的中途调用了MapperScannerRegistrar的registerBeanDefinitions方法MapperScannerRegistrar的registerBeanDefinitions方法中最主要的方法是registerBeanDefinitions方法。

在此处粘贴MapperScannerRegistrar的registerBeanDefinitions方法的内容。

语音识别服务(annotationattributesannoattrs,beandefinitionregistry, string beanname (beandefinitionbuilderbuilder=beandefinitionbuilder.genericbeandefinition (mapperscannerconfigurer.clicurer extendsannotationannotationclass=anno attrs.getclass (annotation class ); if (! annotation.class.equals (annotationclass ) ) builder.addpropertyvalue )、annotation class ); } liststringbasepackages=new ArrayList (; base packages.addall (arrays.stream (anno attrs.getstring array (' value ' ) ).filter (string utils 3360: hastext base packages.addall (arrays.stream (anno attrs.getstring array (' base packages ' ) ).filter (string utils 3360360 haaa Arrays.stream,annoattrs.getclassarray,' basepackageclasses ' ).map,class utils 33603360 g builder.add property value () registry.registerbeandefinition (beanname,builder.getBeanDefinition ); 从registerBeanDefinitions方法中可以看到,这里获取MapperScanner注释中定义的annotationClass、basePackages和basePackageClasses这三个属性,然后使用mapper

3 )观察了映射器配置器类,实现了Bean

DefinitionRegistryPostProcessor接口,那么在SpringBoot的refresh上下文的invokeBeanDefinitionRegistryPostProcessors方法的过程中会调用MapperScannerRegistrar的postProcessBeanDefinitionRegistry方法(这里和MapperScannerRegistrar的registerBeanDefinitions方法调用方法相同,但是入口不同,有兴趣可以看下PostProcessorRegistrationDelegate类,搜索关键字BeanDefinitionRegistryPostProcessor)。

这里我将MapperScannerConfigurer的postProcessBeanDefinitionRegistry方法中的相关内容贴出来:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); scanner.setAnnotationClass(this.annotationClass); scanner.registerFilters(); scanner.scan( StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));}

这里的核心类是ClassPathMapperScanner类(ClassPathMapperScanner类为ClassPathBeanDefinitionScanner类的子类,而ClassPathBeanDefinitionScanner类是SpringBoot批量为Interface生产BeanDefinition工具类)。

首先这里会调用scanner.registerFilters()方法,这里会将MapperScan注解定义的annotationClass属性设置到ClassPathMapperScanner类中,然后调用 scanner.registerFilters(),这个方法的作用是设置一个TypeFilter的方法接口到这个scanner对象的includeFilters属性中。

然后调用scanner.scan( StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS))方法,这里最终会调用ClassPathMapperScanner父类ClassPathBeanDefinitionScanner的doScan方法,doScan方法在扫描到basePackage中的所有接口之后,会调用ClassPathBeanDefinitionScanne持有的所有includeFilters的match方法,判断该类是否满足匹配条件。

简单来说就是接口既要满足被basePackage扫描的条件,又要持有MapperScan注解定义的annotationClass的注解,才会将该接口注入到SpringBoot的BeanDefinitionRegistry组件中。

4,现在回归到我们的自定义工程中,观察SpringBoot启动类,通过之前的源码分析后,可以得出结论,SpringBoot启动容器在加载MapperScan注解的过程中会将com.example.demo.mapper之下所有被Mapper注解修饰的接口注入到SpringBoot的BeanDefinitionRegistry组件中,最后会由SpringBoot根据BeanDefinitionRegistry组件实例化。

5,这里衍生出一个问题,就是一般我们定义启动类的MapperScan的注解,一般只会定义basePackages,而不会去配置annotationClass,那么之前第三步includeFilters集合就为空,那么匹配的条件就是被basePackage扫描的接口都会注入到SpringBoot的BeanDefinitionRegistry组件中。

二、启动类不定义MapperScan注解的方式

1,在MybatisAutoConfiguration类中,存在一个内部类MapperScannerRegistrarNotFoundConfiguration。

如果SpringBoot启动主类不定义MapperScan注解,SpringBoot的BeanDefinitionRegistry组件将不会加载MapperFactoryBean和MapperScannerConfigurer类,那么刚好符合MapperScannerRegistrarNotFoundConfiguration被加载到SpringBoot的BeanDefinitionRegistry组件的条件,而MapperScannerRegistrarNotFoundConfiguration内部类@Import了AutoConfiguredMapperScannerRegistrar类。

2,观察AutoConfiguredMapperScannerRegistrar类,其实现了ImportBeanDefinitionRegistrar类,与MapperScannerRegistrar一样,在SpringBoot的refresh上下文的过程中会调用registerBeanDefinitions方法。

这里我将AutoConfiguredMapperScannerRegistrar的registerBeanDefinitions方法的关键内容贴出来。

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { List<String> packages = AutoConfigurationPackages.get(this.beanFactory); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class); builder.addPropertyValue("annotationClass", Mapper.class); builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class); registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());}

由于自己的启动类根本就没有定义MapperScan注解,所以这里就相当于设置basePackage属性为启动类所在包目录(AutoConfigurationPackages默认获取启动类所在的包)和annotationClass属性为Mapper注解的MapperScannerConfigurer到BeanDefinitionRegistry组件中。

3,回到启动类定义MapperScan注解的方式中的第三步,这里的MapperScannerConfigurer和之前的basePackage属性和annotationClass属性就不同了,在调用MapperScannerConfigurer的postProcessBeanDefinitionRegistry方法的过程中,会将启动类所在包目录下所有带有Mapper注解的接口注入到SpringBoot的BeanDefinitionRegistry组件中。

这里其实可以得出一个结论,当主工程间接依赖到其他的包时,如果想将其他包中带有Mapper注解的接口生成Dao,那么SpringBoot启动类的包名需要包含其他包中带有Mapper注解的接口所在的包。


三、总结:

如果启动类定义了MapperScan注解,那么只有使用了annotationClass属性所定义的注解并且在basePackages属性包下的所有接口,才会被Spring-Boot加载到SpringBoot的BeanDefinitionRegistry组件中,最终生成Dao类。

如果启动类没有定义MapperScan注解,那么只有使用了Mapper注解并且在启动类所在包下的所有接口,才会被Spring-Boot加载到SpringBoot的BeanDefinitionRegistry组件中,最终生成Dao类。

                                                                                                                                                                                                                                          __欢迎关注,后续会更新更多技术干货。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。