mybatis自动扫描mapper的工作原理

2022-08-07 08:05:21

在mybatis中,我们可以在配置文件中使用自动扫描,也就是在mappers中使用package,但是mybatis的扫描原理是什么呢?

首先在mybatis中读取配置文件中的mappers元素,在这个元素中分成两类处理:mapper和package,mapper不在我们的讨论之内,我们只是研究package,这个标签就是自动扫描的配置.

下面是处理package的代码

String mapperPackage = child.getStringAttribute("name");
configuration.addMappers(mapperPackage);

跟踪源码,进入真正扫描将包中的内容是在如下代码
<pre name="code" class="java"> public void addMappers(String packageName, Class<?> superType) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
    for (Class<?> mapperClass : mapperSet) {
      addMapper(mapperClass);
    }
  }
}

下面是我在跟踪源码时mapperSet的内容[class com.min.mapper.ItemsMapperTest, interface com.min.mapper.UserMapper, class com.min.mapper.OrderMapperTest$2, class com.min.mapper.UserMapperTest, class com.min.mapper.OrderMapperTest$1, interface com.min.mapper.ItemsMapper, interface com.min.mapper.OrderMapper, class com.min.mapper.OrderMapperTest]

从中可以看出,这个是先将包中所有的类文件都加载了,在addMapper方法中进行了筛选,代码如下

if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        knownMappers.put(type, new MapperProxyFactory<T>(type));
        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
在addMapper方法中,会对所有的接口生成代理,也就是如果你的不需要生成代理的接口如果放在自动扫描的包中,如果你没有配置相应的xml文件,将会报错,如果你配置了相应的文件,这时将会生成代理对象.
如果你使用mapper已经配置了这个类的代理对象,如果这个类还在扫描包中,这时会报 Type  interface com.min.mapper.UserMapper is already known to the MapperRegistry.l类型已经注册了,

如果当前类没有注册,那么mybatis会先扫描当前包中的类文件,在扫描包中的xml文件,具体代码可以跟踪org.apache.ibatis.binding.MapperRegistry类中的public <T> void addMapper(Class<T> type) 方法.

最后总结一下:

mybatis通过解析全局配置文件,解析到mappers时,在读取其中的所有元素,其中package为自动扫描的包.mybatis会将包中所有的类加载,循环判断其中的接口,并为其生成代理,


  • 作者:_Min
  • 原文链接:https://blog.csdn.net/guaiminbaobao/article/details/46984321
    更新时间:2022-08-07 08:05:21