看了几天源码,说实话看的挺懵逼的。只能写个demo一遍一遍的debugger追踪,看看MyBatis的运行原理到底是怎样的。下面大概看一下typeAliases类型别名的注册流程:
解析MyBatis配置文件configuration节点及子节点时,调用typeAliasesElement()来解析typeAliases属性来完成别名注册。
/**
* typeAliases 类型命名
*/
typeAliasesElement(root.evalNode("typeAliases"));
/**
* 解析MyBatis配置文件 typeAliases类型别名
* @param parent
*/
private void typeAliasesElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
/**
* <typeAliases>
* <package name="hzq.mybatis.source.demo3.entity" />
*</typeAliases>
*/
if ("package".equals(child.getName())) {
/**
*获取MyBatis配置文件的包名称
*/
String typeAliasPackage = child.getStringAttribute("name");
/**
*解析包目录下面的java Bean
*/
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
} else {
/**
* <typeAliases>
* <typeAlias type="hzq.mybatis.source.demo3.entity.User" alias="User"/>
*</typeAliases>
*
*/
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);
}
}
}
}
}
public void registerAliases(String packageName){
registerAliases(packageName, Object.class);
}
/**
* 解析包下面的Java Bean
* Ignore inner classes and interfaces (including package-info.java)
*不包含 内部类,接口 抽象类以及packgee_info类
* @param packageName
* @param superType
*/
public void registerAliases(String packageName, Class<?> superType){
//声明ResolverUtil实例
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
// 利用find函数找到这个包里所有的类,并且放到resolverUtil 的matches属性中
resolverUtil.find(new ResolverUtil.IsA(superType), packageName);
Set<Class<? extends Class<?>>> typeSet = resolverUtil.getClasses();
//循环加载
for(Class<?> type : typeSet){
/**
* 不处理内部类 接口,抽象类以及packgee_info类
*/
// 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);
}
}
}
public void registerAlias(Class<?> type) {
/**
* 获取类的简写名称
*/
String alias = type.getSimpleName();
/**
* @Alias("user")
* 获取javaBean上注解设置的别名
* 这里表示如果采用包方式,没有使用注解设置别名将采用的是类的简写名称,如果使用注解设置别名了,将替换默认的别名
*/
Alias aliasAnnotation = type.getAnnotation(Alias.class);
if (aliasAnnotation != null) {
alias = aliasAnnotation.value();
}
registerAlias(alias, type);
}
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() + "'.");
}
/**
* 添加别名
* private final Map<String, Class<?>> TYPE_ALIASES = new HashMap<String, Class<?>>();
*/
TYPE_ALIASES.put(key, value);
}
public void registerAlias(String alias, String value) {
try {
registerAlias(alias, Resources.classForName(value));
} catch (ClassNotFoundException e) {
throw new TypeException("Error registering type alias "+alias+" for "+value+". Cause: " + e, e);
}
}
以上是MyBatis配置typeAliases别名的全部过程。MyBatis的源码路程还很漫长,但是从来不放弃进步的脚步。加油!!!