本篇文章我们继续来了解typeHandlers标签,这个标签的作用主要就是用于Java类型和数据库字段类型的相互转换.
基本用法为:
<typeHandlers>
<typeHandler handler="" javaType="" jdbcType=""></typeHandler>
<package name=""></package>
</typeHandlers>
我们直接来看typeHandlerElement(root.evalNode(“typeHandlers”))方法的代码:
private void typeHandlerElement(XNode parent) throws Exception {
if (parent != null) {
// 遍历typeHandlers下所有子标签
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
// 若是package子标签,则使用typeHandlerRegistry的register方法去注册类型处理器
// typeHandlerRegistry也是在BaseBuilder构造方法中从Configuration拿出来的(和typeAliasRegistry一样)
String typeHandlerPackage = child.getStringAttribute("name");
typeHandlerRegistry.register(typeHandlerPackage);
} else {
String javaTypeName = child.getStringAttribute("javaType");
String jdbcTypeName = child.getStringAttribute("jdbcType");
String handlerTypeName = child.getStringAttribute("handler");
// 通过别名获取javaType的Class对象
Class<?> javaTypeClass = resolveClass(javaTypeName);
// 通过jdbcType获取JdbcType对象
JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
// 通过别名获取handler的Class对象
Class<?> typeHandlerClass = resolveClass(handlerTypeName);
// 通过不同的条件去注册类型处理器
if (javaTypeClass != null) {
if (jdbcType == null) {
typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
} else {
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
}
} else {
typeHandlerRegistry.register(typeHandlerClass);
}
}
}
}
}
从上述代码能看出,最终都将调用typeHandlerRegistry的register方法的各中重载形式.
我们先来看子标签为package时,使用的注册一个包中所有的typeHandler的register方法:
public void register(String packageName) {
// 查找该包下所有实现了TypeHandler接口的类
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
for (Class<?> type : handlerSet) {
// 当该类不是内部内或接口或者抽象类时,注册类型处理器
if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
register(type);
}
}
}
public void register(Class<?> typeHandlerClass) {
boolean mappedTypeFound = false;
// 看该类上是否使用了MappedTypes注解
MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
for (Class<?> javaTypeClass : mappedTypes.value()) {
register(javaTypeClass, typeHandlerClass);
mappedTypeFound = true;
}
}
if (!mappedTypeFound) {
register(getInstance(null, typeHandlerClass));
}
}
从上述代码中可以看出,若使用了MappedTypes注解,则继续调用register(javaTypeClass, typeHandlerClass)方法:
public void register(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
register(javaTypeClass, getInstance(javaTypeClass, typeHandlerClass));
}
private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {
// 看该类上是否使用了MappedJdbcTypes注解
MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
// 最终都是去调用register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler)方法
if (mappedJdbcTypes != null) {
for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
register(javaType, handledJdbcType, typeHandler);
}
if (mappedJdbcTypes.includeNullJdbcType()) {
register(javaType, null, typeHandler);
}
} else {
register(javaType, null, typeHandler);
}
}
public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandlerClass) {
if (javaTypeClass != null) {
// 若javaTypeClass不为null,则调用typeHandlerClass的有参构造方法,构造一个TypeHandler
try {
Constructor<?> c = typeHandlerClass.getConstructor(Class.class);
return (TypeHandler<T>) c.newInstance(javaTypeClass);
} catch (NoSuchMethodException ignored) {
// ignored
} catch (Exception e) {
throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
}
}
// 若javaTypeClass为null,则调用typeHandlerClass的无参构造方法,构造一个TypeHandler
try {
Constructor<?> c = typeHandlerClass.getConstructor();
return (TypeHandler<T>) c.newInstance();
} catch (Exception e) {
throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
}
}
我们来看看最终调用的register方法:
private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
if (javaType != null) {
// 查看当前javaType是否有对应的类型处理器,如果没有则新建
// 如果有,则将该javaType到jdbcType映射对应的类型处理器加入map中
Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType);
if (map == null) {
map = new HashMap<JdbcType, TypeHandler<?>>();
TYPE_HANDLER_MAP.put(javaType, map);
}
map.put(jdbcType, handler);
// 若是对包装类的javaType注册处理器映射器,则同时也给对应的基本类型注册
if (reversePrimitiveMap.containsKey(javaType)) {
register(reversePrimitiveMap.get(javaType), jdbcType, handler);
}
}
// 所有的映射器Class和实例的映射map
ALL_TYPE_HANDLERS_MAP.put(handler.getClass(), handler);
}
综上,我们可以看出,TypeHandlerRegistry内部最重要的是TYPE_HANDLER_MAP.是一个Map结构,key为java类型,value还是一个Map结构,该Map结构的key是jdbc类型,value是一个typeHandler.
所以,我们可以看出,一个java类型,可以对应多个jdbc类型,对应的每个jdbc类型都有其typeHandler.