@MapperScan扫描

@MapperScan扫描@MapperScan@MapperScan({“com.kq.mybatis.mapper”,”com.kq.mybatis1.mapper”})publicvoidregisterBeanDefinitions(AnnotationMetadataimportingClassMetadata,BeanDefinitionRegistryregistry){AnnotationAttributesmapperScanAttrs=AnnotationAttribute

大家好,又见面了,我是你们的朋友全栈君。

@MapperScan

@MapperScan({"com.kq.mybatis.mapper","com.kq.mybatis1.mapper"})
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    AnnotationAttributes mapperScanAttrs = AnnotationAttributes
        .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScan.class.getName()));
    if (mapperScanAttrs != null) {
      registerBeanDefinitions(mapperScanAttrs, registry, generateBaseBeanName(importingClassMetadata, 0));
    }
  }

 

这样是默认扫描com.kq.mybatis.mapper和com.kq.mybatis1.mapper包下的所有.clsss文件,而不是扫描这2个包下的所有Mapper文件

@MapperScan扫描

@MapperScan指定markerInterface

这里通过@MapperScan指定markerInterface,这样扫描出来的都是实现该接口的Mapper

@MapperScan(value = {"com.kq.scan.mybatis.mapper","com.kq.scan.mybatis1.mapper"},markerInterface = MybatisBaseMapper.class)


public interface AccountMapper extends MybatisBaseMapper {  }

这个markerInterface 最终设置的是MapperScannerConfigurer markerInterface属性

@MapperScan指定annotationClass


@MapperScan(value = {"com.kq.scan.mybatis.mapper","com.kq.scan.mybatis1.mapper"},markerInterface = MybatisBaseMapper.class,annotationClass=Mapper.class)


@Mapper
public interface UserMapper { }

这个annotationClass最终设置的是MapperScannerConfigurer annotationClass属性

注意:

@MapperScan同时指定markerInterface 和 annotationClass 两个元素的时候,只要1个条件满足,就算符合条件,而不是要两个条件都满足

 

MapperScannerRegistrar

BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
    builder.addPropertyValue("processPropertyPlaceHolders", true);

    Class<? extends Annotation> annotationClass = annoAttrs.getClass("annotationClass");
    if (!Annotation.class.equals(annotationClass)) {
      builder.addPropertyValue("annotationClass", annotationClass);
    }

    // 看这里 markerInterface
    Class<?> markerInterface = annoAttrs.getClass("markerInterface");
    if (!Class.class.equals(markerInterface)) {
      builder.addPropertyValue("markerInterface", markerInterface);
}

 

@MapperScans

@MapperScans({@MapperScan("com.kq.mybatis.mapper"),@MapperScan("com.kq.mybatis1.mapper")})
static class RepeatingRegistrar extends MapperScannerRegistrar {
   
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
      AnnotationAttributes mapperScansAttrs = AnnotationAttributes
          .fromMap(importingClassMetadata.getAnnotationAttributes(MapperScans.class.getName()));
      if (mapperScansAttrs != null) {
        AnnotationAttributes[] annotations = mapperScansAttrs.getAnnotationArray("value");
        for (int i = 0; i < annotations.length; i++) {
          registerBeanDefinitions(annotations[i], registry, generateBaseBeanName(importingClassMetadata, i));
        }
      }
    }
  }

@MapperScan扫描

使用@MapperScans,spring的bean定义,注册的MapperScannerRegistrar 有多个的,看上图

 

注意

每个@MapperScan最终都会初始化1个MapperScannerConfigurer,主要关键的属性basePackage、annotationClass、markerInterface

 

主要相关类

org.mybatis.spring.annotation.MapperScannerRegistrar
org.mybatis.spring.mapper.MapperScannerConfigurer

类图

@MapperScan扫描

@MapperScan扫描

 

总结

@MapperScan主要就是扫描得到mybatis的Mapper,并最终在Spring容器种初始化

 

未配置@MapperScan

org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
/**
   * If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan
   * mappers based on the same component-scanning path as Spring Boot itself.
   */
  @org.springframework.context.annotation.Configuration
  @Import(AutoConfiguredMapperScannerRegistrar.class)
  @ConditionalOnMissingBean({ MapperFactoryBean.class, MapperScannerConfigurer.class })
  public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {

    @Override
    public void afterPropertiesSet() {
      logger.debug(
          "Not found configuration for registering mapper bean using @MapperScan, MapperFactoryBean and MapperScannerConfigurer.");
    }

  }

重点看下面这句话

If mapper registering configuration or mapper scanning configuration not present, this configuration allow to scan
    mappers based on the same component-scanning path as Spring Boot itself.

(如果不存在mapper注册配置或mapper扫描配置,则此配置允许扫描mapper基于与Spring Boot本身相同的组件扫描路径。)

 

AutoConfiguredMapperScannerRegistrar 

org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

public static class AutoConfiguredMapperScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar {

    private BeanFactory beanFactory;

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

      if (!AutoConfigurationPackages.has(this.beanFactory)) {
        logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.");
        return;
      }

      logger.debug("Searching for mappers annotated with @Mapper");

      List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
      if (logger.isDebugEnabled()) {
        packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
      }

      BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MapperScannerConfigurer.class);
      builder.addPropertyValue("processPropertyPlaceHolders", true);
      builder.addPropertyValue("annotationClass", Mapper.class); //指定扫描的注解
      builder.addPropertyValue("basePackage", StringUtils.collectionToCommaDelimitedString(packages)); //和springboot一致
      BeanWrapper beanWrapper = new BeanWrapperImpl(MapperScannerConfigurer.class);
      Stream.of(beanWrapper.getPropertyDescriptors())
          // Need to mybatis-spring 2.0.2+
          .filter(x -> x.getName().equals("lazyInitialization")).findAny()
          .ifPresent(x -> builder.addPropertyValue("lazyInitialization", "${mybatis.lazy-initialization:false}"));
      registry.registerBeanDefinition(MapperScannerConfigurer.class.getName(), builder.getBeanDefinition());
    }

    

 }

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/137423.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C++ — TranslateMessage函数

    C++ — TranslateMessage函数TranslateMessage是用来把虚拟键消息转换为字符消息。由于Windows对所有键盘编码都是采用虚拟键的定义,这样当按键按下时,并不得字符消息,需要键盘映射转换为字符的消息。 TranslateMes…

    2025年9月4日
    8
  • 洗牌算法思路_随机洗牌算法

    洗牌算法思路_随机洗牌算法1.背景    笔试时,遇到一个算法题:差不多是在n个不同的数中随机取出不重复的m个数。洗牌算法是将原来的数组进行打散,使原数组的某个数在打散后的数组中的每个位置上等概率的出现,刚好可以解决该问题。2.洗牌算法    由抽牌、换牌和插牌衍生出三种洗牌算法,其中抽牌和换牌分别对应Fisher-YatesShuffle和Knuth-DurstenfeldShhuffle算法。 …

    2022年9月21日
    3
  • linux 解压war到root_unzip命令解压war包方法

    linux 解压war到root_unzip命令解压war包方法unzip 命令用于解压缩由 zip 命令压缩的 zip 压缩包 语法 unzip 选项 参数 选项 c 将解压缩的结果显示到屏幕上 并对字符做适当的转换 f 更新现有的文件 l 显示压缩文件内所包含的文件 p 与 c 参数类似 会将解压缩的结果显示到屏幕上 但不会执行任何的转换 t 检查压缩文件是否正确 u 与 f 参数类似 但是除了更新现有的文件外 也会将压缩文件中的其他文件解压缩到目录中

    2025年8月3日
    1
  • JAX-WS与JAX-RS区别是什么?

    JAX-WS与JAX-RS区别是什么?一、JAX-WS:全称是JavaTMAPIforXML-BasedWebServicesJAX-RS:全称是JavaTMAPIforRESTfulWebServices关于JAX-WS与JAX-RS两者是不同风格的SOA架构。前者以动词为中心,指定的是每次执行函数。而后者以名词为中心,每次执行的时候指的是资源。二、JAX-RS是JAVAEE6引入的一个新技术。JAX…

    2022年7月15日
    11
  • 为何asp.net2.0中 rendercontrol 对于有些服务器端的控件会不支持[通俗易懂]

    为何asp.net2.0中 rendercontrol 对于有些服务器端的控件会不支持[通俗易懂]比如报出rendercontrol必须放在具有runat=server这样的错误原因:http://topic.csdn.net/t/20051207/21/4444706.html解决方法:http://www.cnblogs.com/zhangronghua/archive/2008/11/07/951899.html

    2022年7月20日
    20
  • idea 2021.3.4激活码(JetBrains全家桶)[通俗易懂]

    (idea 2021.3.4激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月27日
    423

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号