mybatis注册类型别名

mybatis在xml文件中可以处理类型别名,根据别名获取实体类,具体是在SqlSessionFactoryBean.java#buildSqlSessionFactory(),typeAliasesPackage是mybatis.type-aliases-package配置项指定的包路径,可以指定多个,多个之间可以用",; \t\n"隔开。

// SqlSessionFactoryBean
    if (hasLength(this.typeAliasesPackage)) {
      String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
          ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
      for (String packageToScan : typeAliasPackageArray) {
        //默认typeAliasesSuperType是Object
        configuration.getTypeAliasRegistry().registerAliases(packageToScan,
                typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
        if (LOGGER.isDebugEnabled()) {
          LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
        }
      }
    }

处理类型别名的是TypeAliasRegistryprotected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();,即由TypeAliasRegistry#registerAliases()方法处理。

  public void registerAliases(String packageName, Class<?> superType){
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
    resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
    Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
    for(Class<?> type : typeSet){
      // Ignore inner classes and interfaces (including package-info.java)
      // Skip also inner classes. See issue #6
      if (!type.isAnonymousClass() && !type.isInterface() && !type.isMemberClass()) {
        registerAlias(type);
      }
    }
  }

这里就是根据包路径找到所有的class,

  public ResolverUtil<T> find(Test test, String packageName) {
    String path = getPackagePath(packageName);

    try {
      //找出path下所有的class路径全称  
      List<String> children = VFS.getInstance().list(path);
      for (String child : children) {
        if (child.endsWith(".class")) {
          addIfMatching(test, child);
        }
      }
    } catch (IOException ioe) {
      log.error("Could not read package: " + packageName, ioe);
    }

    return this;
  }

  public List<String> list(String path) throws IOException {
    List<String> names = new ArrayList<String>();
    for (URL url : getResources(path)) {
      names.addAll(list(url, path));
    }
    return names;
  }

  protected List<String> list(URL url, String path) throws IOException {
    Resource[] resources = resourceResolver.getResources("classpath*:" + path + "/**/*.class");
    List<String> resourcePaths = new ArrayList<String>();
    for (Resource resource : resources) {
      resourcePaths.add(preserveSubpackageName(resource.getURI(), path));
    }
    return resourcePaths;
  }  

首先将返回的class路径全称最后的.class去掉,然后将’/‘换成’.',这样就能得到Java语法格式的class路径名,然后使用类加载器进行加载就能得到Class。

  protected void addIfMatching(Test test, String fqn) {
    try {
      String externalName = fqn.substring(0, fqn.indexOf('.')).replace('/', '.');
      ClassLoader loader = getClassLoader();
      if (log.isDebugEnabled()) {
        log.debug("Checking to see if class " + externalName + " matches criteria [" + test + "]");
      }

      Class<?> type = loader.loadClass(externalName);
      if (test.matches(type)) {
        matches.add((Class<T>) type);
      }
    } catch (Throwable t) {
      log.warn("Could not examine class '" + fqn + "'" + " due to a " +
          t.getClass().getName() + " with message: " + t.getMessage());
    }
  }

    public boolean matches(Class<?> type) {
      return type != null && parent.isAssignableFrom(type);
    }

最后最关键的一步是注册别名,首先通过class获取别名,一般是类名大写,如果用了@Alias,则使用@Alias注解指定的别名进行注册。

  public void registerAlias(Class<?> type) {
    String alias = type.getSimpleName();
    Alias aliasAnnotation = type.getAnnotation(Alias.class);
    if (aliasAnnotation != null) {
      alias = aliasAnnotation.value();
    } 
    registerAlias(alias, type);
  }

注册的时候别名全小写,最后是保存到private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();,之后我们在xml中就可以通过别名引用了。

  public void registerAlias(String alias, Class<?> value) {
    if (alias == null) {
      throw new TypeException("The parameter alias cannot be null");
    }
    // issue #748
    String key = alias.toLowerCase(Locale.ENGLISH);
    if (TYPE_ALIASES.containsKey(key) && TYPE_ALIASES.get(key) != null && !TYPE_ALIASES.get(key).equals(value)) {
      throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + TYPE_ALIASES.get(key).getName() + "'.");
    }
    TYPE_ALIASES.put(key, value);
  }

总结一下,mybatis会根据配置项mybatis.type-aliases-package的值获取类别名路径,然后到路径下扫描获取路径下所有的class文件,在替换成Java语法格式class路径,然后使用类加载器进行加载得到Class对象。接着获取类的别名,可以用@Alias指定,没有就是类的小写全称,最终是保存到map中。有不对的地方请大神指出,欢迎大家一起讨论交流,共同进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: typeAliasesElement 在 MyBatis 中用于定义类型别名。在解析过程中,MyBatis 首先会将其中的类型别名注册到它的类型别名注册器中。然后,在执行 SQL 语句时,MyBatis 就可以使用这些类型别名来解析映射关系。 具体来说,当 MyBatis 在解析 typeAliasesElement 时,会执行以下步骤: 1. 遍历所有的类型别名元素。 2. 对于每个类型别名元素,获取其中的类型别名和类名。 3. 将类型别名与类名注册类型别名注册器中。 4. 重复步骤 1-3,直到遍历完所有的类型别名元素。 在解析过程中,MyBatis 会使用类加载器加载类型别名所对应的类。这样,在执行 SQL 语句时,MyBatis 就可以使用这些类来解析映射关系。 ### 回答2: mybatistypeAliasesElement是一个XML元素,用于定义类型别名。它的解析过程如下: 1. 在mybatis的配置文件中,我们可以使用typeAliasesElement来定义类型别名。它是在<configuration>标签内部使用的。 2. 当mybatis解析配置文件时,会解析typeAliasesElement元素。 3. 解析过程中,首先会获取typeAliasesElement元素的属性值,如aliastype。 4. 如果type属性有值,表示我们要为某个类定义一个别名mybatis会通过反射机制获取到该类的全限定名,并将别名和类的全限定名进行映射。 5. 如果alias属性有值,表示我们要为一个包路径定义别名mybatis会扫描该包下的所有类,并将类名和别名进行映射。 6. 解析完成后,mybatis会将这些别名和类的映射关系存储起来,供后续使用。 总的来说,mybatistypeAliasesElement解析过程就是将类或包路径与别名进行映射,以方便在mapper文件中使用别名来代替具体的类名。这样可以简化mapper文件的编写,提高开发效率。同时也使得mapper文件的可读性更强,更易于维护。 ### 回答3: mybatis中的typeAliasesElement是用来解析类型别名的元素。在mybatis的配置文件中可以使用typeAliasesElement来定义类型别名,它的作用是为了在使用mapper文件中的resultType、parameterTypetypeHandler等地方时可以直接使用类型别名代替具体的类名。 解析typeAliasesElement的过程如下: 1. 首先,解析器会读取mybatis的配置文件中的typeAliasesElement元素。 2. 然后,解析器会获取typeAliasesElement元素中的所有子元素。 3. 解析器会遍历所有子元素,并将每个子元素的name和type属性值分别获取到。 4. 接下来,解析器会将name和type属性值进行解析和处理。 5. 对于name属性值,解析器会将其作为类型别名来处理。 6. 对于type属性值,解析器会使用反射的方式获取该属性值对应的类型,并将其作为name属性值对应的类型。 7. 最后,解析器会将得到的name和type属性值建立映射关系,并存储到mybatis类型别名注册表中。 通过上述解析过程,我们可以在mapper文件中直接使用类型别名来指定resultType、parameterTypetypeHandler等属性值,而无需使用具体的类名。这样可以简化配置,提高代码的可读性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值