mybatis源码解读(7)
来源:互联网 发布:西门子em235编程 编辑:程序博客网 时间:2024/06/05 16:17
typeAliases别名机制解析
private void typeAliasesElement(XNode parent) { if (parent != null) { for (XNode child : parent.getChildren()) { if ("package".equals(child.getName())) { String typeAliasPackage = child.getStringAttribute("name"); configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage); } else { String alias = child.getStringAttribute("alias"); String type = child.getStringAttribute("type"); try { Class<?> clazz = Resources.classForName(type); if (alias == null) { typeAliasRegistry.registerAlias(clazz); } else { typeAliasRegistry.registerAlias(alias, clazz); } } catch (ClassNotFoundException e) { throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e); } } } } }
<typeAliases> <typeAlias alias="Author" type="domain.blog.Author"/> <typeAlias alias="Blog" type="domain.blog.Blog"/> <typeAlias alias="Comment" type="domain.blog.Comment"/> <typeAlias alias="Post" type="domain.blog.Post"/> <typeAlias alias="Section" type="domain.blog.Section"/> <typeAlias alias="Tag" type="domain.blog.Tag"/></typeAliases>
或者
<typeAliases> <package name="domain.blog"/></typeAliases>
文件的解析很简单,循环他的子节点,然后判断节点的类型,是package还是typeAlias,执行相应的逻辑。
我们先来看typeAlias的逻辑。
if (alias == null) { typeAliasRegistry.registerAlias(clazz);} else { typeAliasRegistry.registerAlias(alias, clazz);}
这个可以看出type是必填项,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); }
不传别名的注册:
拿到类的simpleName(即不包含包名的类名)。再去获取该类是否有Alias注解。
这个逻辑可以看出,对于不写别名的类型,如果写了Alias注解,已注解的为准,如果没写注解,就使用类的简单名称(这里原来大写还是大写)。
public void registerAlias(String alias, Class<?> value) { if (alias == null) throw new TypeException("The parameter alias cannot be null"); String key = alias.toLowerCase(Locale.ENGLISH); // issue #748 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); }
可以看到,这里的别名统一转成了小写,然后放到一个map中。
org.apache.ibatis.type.TypeAliasRegistry#TypeAliasRegistry
查看TypeAliasRegistry的构造方法。
registerAlias("string", String.class);registerAlias("byte", Byte.class);registerAlias("long", Long.class);...
最后我们看下package的别名注册:
public void registerAliases(String packageName){ registerAliases(packageName, Object.class); } 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); } } }
这里的逻辑也比较简单,查找包下的类,一一注册成别名就可以了。
这里有特定的是ResolverUtil这个工具类。也不掉大家胃口了,看看他是怎么实现查找包下的类的。
这个类下有个集合,是存放查找结果的
/** The set of matches being accumulated. */ private Set<Class<? extends T>> matches = new HashSet<Class<? extends T>>();
里面的find方法
public ResolverUtil<T> find(Test test, String packageName) { String path = getPackagePath(packageName); try { 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; }
getPackagePath把包路径的“.”换成“/”,然后用VFS.getInstance().list(path)来获取该路径下的文件,这个查找文件是通过
Collections.list(Thread.currentThread().getContextClassLoader().getResources(path));
来获取的,然后还要经过一次list的转换,这下面就比较复杂了。有兴趣的同学可以继续往下看,我们再深入就没完没了了。
这里注册了很多默认的别名。以上即别名机制的全部内容。其实很简单是不是。看了源码,别名是不是就可以用的很6了。
- mybatis源码解读(7)
- mybatis源码解读(1)
- mybatis源码解读(2)
- mybatis源码解读(3)
- mybatis源码解读(5)
- mybatis源码解读(6)
- mybatis源码解读(8)
- Mybatis源码解读
- mybatis之MapperFactoryBean源码解读
- MyBatis插件原理-源码解读
- MyBatis的Sql执行过程源码解读
- mybatis--源码解读---XML的解析
- Mybatis如何加载配置文件 源码解读parameterType
- mybatis源码中的设计模式解读
- Mybatis源码解读——Mybatis demo工作流程
- 源码解读Mybatis List列表In查询实现的注意事项
- 源码解读Mybatis List列表In查询实现的注意事项
- 源码解读Mybatis List列表In查询实现的注意事项
- 黑马程序员_图形用户界面
- iOS 动态设置Label的高度,行与行之间有间隔
- 解决centos6系统pptpd服务的619错误
- 第六周 项目四-成员函数、友元函数和一般函数有区别 阅读
- GetWindowRect和GetClientRect的区别详解
- mybatis源码解读(7)
- SVN服务器搭建和使用
- hbuilder 找不到模拟器
- C++ 宏定义实现单例模式
- visual assist 破解方法
- GDB命令
- 在WebView中获取网页中的内容
- Spring AOP execution
- C语言文件操作解析(五)之EOF解析