public class XPathParser {
private final Document document;
//是否开启验证
private boolean validation;
//加载本地DTD
private EntityResolver entityResolver;
//Properties标签定义值
private Properties variables;
private XPath xpath;
}
spring专栏有自定义命名空间解析,就不阐述了
public class XMLMapperEntityResolver implements EntityResolver {
//指定mybatis-config.xml的DTD
private static final String IBATIS_CONFIG_SYSTEM = "ibatis-3-config.dtd";
private static final String IBATIS_MAPPER_SYSTEM = "ibatis-3-mapper.dtd";
private static final String MYBATIS_CONFIG_SYSTEM = "mybatis-3-config.dtd";
private static final String MYBATIS_MAPPER_SYSTEM = "mybatis-3-mapper.dtd";
//指定dtd位置
private static final String MYBATIS_CONFIG_DTD = "org/apache/ibatis/builder/xml/mybatis-3-config.dtd";
private static final String MYBATIS_MAPPER_DTD = "org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd";
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
try {
if (systemId != null) {
String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
//查找sysId指定的DTD文档,并读取
if (lowerCaseSystemId.contains(MYBATIS_CONFIG_SYSTEM) || lowerCaseSystemId.contains(IBATIS_CONFIG_SYSTEM)) {
return getInputSource(MYBATIS_CONFIG_DTD, publicId, systemId);
} else if (lowerCaseSystemId.contains(MYBATIS_MAPPER_SYSTEM) || lowerCaseSystemId.contains(IBATIS_MAPPER_SYSTEM)) {
return getInputSource(MYBATIS_MAPPER_DTD, publicId, systemId);
}
}
return null;
} catch (Exception e) {
throw new SAXException(e.toString());
}
}
}
public XPathParser(String xml) {
//构造时,初始化xpath
commonConstructor(false, null, null);
this.document = createDocument(new InputSource(new StringReader(xml)));
}
private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
this.validation = validation;
this.entityResolver = entityResolver;
this.variables = variables;
XPathFactory factory = XPathFactory.newInstance();
this.xpath = factory.newXPath();
}
private Document createDocument(InputSource inputSource) {
// important: this must only be called AFTER common constructor
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setValidating(validation);
factory.setNamespaceAware(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(false);
factory.setCoalescing(false);
factory.setExpandEntityReferences(true);
DocumentBuilder builder = factory.newDocumentBuilder();
//设置DTD解析器
builder.setEntityResolver(entityResolver);
builder.setErrorHandler(new ErrorHandler() {
@Override
public void error(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void warning(SAXParseException exception) throws SAXException {
// NOP
}
});
//加载XML
return builder.parse(inputSource);
} catch (Exception e) {
throw new BuilderException("Error creating document instance. Cause: " + e, e);
}
}
public String evalString(Object root, String expression) {
String result = (String) evaluate(expression, root, XPathConstants.STRING);
//设置节点默认值
result = PropertyParser.parse(result, variables);
return result;
}
public static String parse(String string, Properties variables) {
VariableTokenHandler handler = new VariableTokenHandler(variables);
//指定处理的占位符格式为${}
GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
return parser.parse(string);
}
public class GenericTokenParser {
//占位符开始标记
private final String openToken;
//占位符结束标记
private final String closeToken;
//解析占位符
private final TokenHandler handler;
/**
* 将text根据前后占位符解析
* @param text
* @return
*/
public String parse(String text) {
if (text == null || text.isEmpty()) {
return "";
}
// search open token
//查找第一个开启占位符位置
int start = text.indexOf(openToken);
if (start == -1) {
return text;
}
char[] src = text.toCharArray();
int offset = 0;
//线程安全,记录占位符的值
final StringBuilder builder = new StringBuilder();
StringBuilder expression = null;
while (start > -1) {
if (start > 0 && src[start - 1] == '\\') {
// this open token is escaped. remove the backslash and continue.
//遇到转义的开始标记,直接将前面的字符串以及开始标记追加
builder.append(src, offset, start - offset - 1).append(openToken);
offset = start + openToken.length();
} else {
// found open token. let's search close token.
//查找到开始标记,且未转义
if (expression == null) {
expression = new StringBuilder();
} else {
expression.setLength(0);
}
//前面字符追加
builder.append(src, offset, start - offset);
offset = start + openToken.length();
//从offset后继续查找结束标记
int end = text.indexOf(closeToken, offset);
while (end > -1) {
if (end > offset && src[end - 1] == '\\') {
// this close token is escaped. remove the backslash and continue.
//处理转义的结束标记
expression.append(src, offset, end - offset - 1).append(closeToken);
offset = end + closeToken.length();
end = text.indexOf(closeToken, offset);
} else {
//将开始标记和结束标记之间字符添加
expression.append(src, offset, end - offset);
break;
}
}
if (end == -1) {
//未找到结束标记
// close token was not found.
builder.append(src, start, src.length - start);
offset = src.length;
} else {
//将占位符的值交给handler处理,并保存builder
builder.append(handler.handleToken(expression.toString()));
offset = end + closeToken.length();
}
}
//移动start
start = text.indexOf(openToken, offset);
}
if (offset < src.length) {
builder.append(src, offset, src.length - offset);
}
return builder.toString();
}
}
private static class VariableTokenHandler implements TokenHandler {
//Properties标签定义值,用于替换占位符
private final Properties variables;
//是否支持占位符中使用默认的功能
private final boolean enableDefaultValue;
//指定占位符和默认值之间的分隔符
private final String defaultValueSeparator;
@Override
public String handleToken(String content) {
//variables非空
if (variables != null) {
String key = content;
//是否支持占位符中使用默认值功能
if (enableDefaultValue) {
//查找分割符
final int separatorIndex = content.indexOf(defaultValueSeparator);
String defaultValue = null;
if (separatorIndex >= 0) {
//获取占位符名称
key = content.substring(0, separatorIndex);
//获取默认值
defaultValue = content.substring(separatorIndex + defaultValueSeparator.length());
}
if (defaultValue != null) {
//查找指定占位符
return variables.getProperty(key, defaultValue);
}
}
//不支持默认值,则直接找
if (variables.containsKey(key)) {
return variables.getProperty(key);
}
}
//variables空
return "${" + content + "}";
}
}
public List<XNode> evalNodes(Object root, String expression) {
//XNode,mybatis实现,封装node
List<XNode> xnodes = new ArrayList<>();
NodeList nodes = (NodeList) evaluate(expression, root, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
xnodes.add(new XNode(this, nodes.item(i), variables));
}
return xnodes;
}
public class XNode {
//w3c对象
private final Node node;
//节点名
private final String name;
//节点内容
private final String body;
//节点属性集合
private final Properties attributes;
//Properties对应配置文件
private final Properties variables;
private final XPathParser xpathParser;
public XNode(XPathParser xpathParser, Node node, Properties variables) {
this.xpathParser = xpathParser;
this.node = node;
this.name = node.getNodeName();
this.variables = variables;
this.attributes = parseAttributes(node);
this.body = parseBody(node);
}
private Properties parseAttributes(Node n) {
Properties attributes = new Properties();
//获取节点的属性集合
NamedNodeMap attributeNodes = n.getAttributes();
if (attributeNodes != null) {
for (int i = 0; i < attributeNodes.getLength(); i++) {
Node attribute = attributeNodes.item(i);
//使用PropertyParser 处理每个属性中的占位符
String value = PropertyParser.parse(attribute.getNodeValue(), variables);
attributes.put(attribute.getNodeName(), value);
}
}
return attributes;
}
private String parseBody(Node node) {
String data = getBodyData(node);
//当前节点不是文本节点
if (data == null) {
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
data = getBodyData(child);
if (data != null) {
break;
}
}
}
return data;
}
private String getBodyData(Node child) {
//只处理文本内容
if (child.getNodeType() == Node.CDATA_SECTION_NODE
|| child.getNodeType() == Node.TEXT_NODE) {
String data = ((CharacterData) child).getData();
//使用PropertyParser 处理文本节点中的占位符
data = PropertyParser.parse(data, variables);
return data;
}
return null;
}
}
public class Reflector {
//对应的Class 类型
private final Class<?> type;
//可读属性的名称集合,可读属性就是存在相应getter 方法的属性,初始值为空数纽
private final String[] readablePropertyNames;
//可写属性的名称集合,可写属性就是存在相应setter 方法的属性,初始值为空数纽
private final String[] writablePropertyNames;
//记录了属性相应的setter 方法, key 是属性名称, value 是Invoker 对象
private final Map<String, Invoker> setMethods = new HashMap<>();
//属性相应的getter 方法集合, key 是属性名称, value 也是Inv o ker 对象
private final Map<String, Invoker> getMethods = new HashMap<>();
//记录了属性相应的setter 方法的参数值类型, ke y 是属性名称, value 是setter 方法的参数类型
private final Map<String, Class<?>> setTypes = new HashMap<>();
//记录了属性相应的getter 方法的返回位类型, key 是属性名称, value 是getter 方法的返回位类型
private final Map<String, Class<?>> getTypes = new HashMap<>();
//记录了默认构造方法
private Constructor<?> defaultConstructor;
//记录了所有属性名称的集合
private Map<String, String> caseInsensitivePropertyMap = new HashMap<>();
public Reflector(Class<?> clazz) {
type = clazz;
//查找clazz 的默认构造方法(无参构造方法)
addDefaultConstructor(clazz);
//处理clazz 中的getter 方法,填充getMethods 集合和getTypes 集合
addGetMethods(clazz);
//处理clazz 中的set ter 方法,填充setMethods 集合和set Types 集合
addSetMethods(clazz);
//处理没有g etter I setter 方法的字段
addFields(clazz);
//根据getMethodslsetMethods 集合,初始化可读/写属性的名称集合
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
//初始化caseinsensitivePropertyMap 集合,其中记录了所有大写格式的属性名称
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
/**
* 填充getMethods 集合和getTypes 集合
* @param clazz
*/
private void addGetMethods(Class<?> clazz) {
Map<String, List<Method>> conflictingGetters = new HashMap<>();
//获取指定类以及其父类和接口中定义的方法
Method[] methods = getClassMethods(clazz);
//对get方法过滤
Arrays.stream(methods).filter(m ->
//JavaBean 中getter 方法的方法名长度大于3 且必须以” get ” 开头
m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
.forEach(m ->
//记录到conflictingGetters集合中
addMethodConflict(conflictingGetters,
//获取对应的属性名称
PropertyNamer.methodToProperty(m.getName()), m));
//对方法同名返回值不一样的处理
resolveGetterConflicts(conflictingGetters);
}
private Method[] getClassMethods(Class<?> clazz) {
//用于记录指定类中定义的全部方法的唯一签名以及对应的Meth od 对象
Map<String, Method> uniqueMethods = new HashMap<>();
Class<?> currentClass = clazz;
while (currentClass != null && currentClass != Object.class) {
//记录currentClass 这个类中定义的全部方法.桥方法除外
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// we also need to look for interface methods -
// because the class may be abstract
//记录接口中定义的方法
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
//获取父类,继续while 循环
currentClass = currentClass.getSuperclass();
}
Collection<Method> methods = uniqueMethods.values();
return methods.toArray(new Method[0]);
}
private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
for (Method currentMethod : methods) {
//过滤桥接方法,也就是为了兼容泛型,重新定义了一个方法,调用原来的方法,定位桥
if (!currentMethod.isBridge()) {
//方法得到的方法签名是全局唯一的,可以作为该方法 的唯一标识
String signature = getSignature(currentMethod);
// check to see if the method is already known
// if it is known, then an extended class must have
// overridden a method
//检测是否在子类中已经添加过该方法,如果在子类中已经添加过,无须再向uniqueMethods 集合中添加该方法了
if (!uniqueMethods.containsKey(signature)) {
//记录该签名和方法的对应关系
uniqueMethods.put(signature, currentMethod);
}
}
}
}
}
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
Method winner = null;
String propName = entry.getKey();
boolean isAmbiguous = false;
for (Method candidate : entry.getValue()) {
if (winner == null) {
winner = candidate;
continue;
}
//同一属性名称存在多个getter方法,则需要比较这些getter方法的返回,选择getter方法
//迭代过程中的临时变量,用于记录迭代到目前为止,最适合作为getter 方法的Method
Class<?> winnerType = winner.getReturnType();
Class<?> candidateType = candidate.getReturnType();
if (candidateType.equals(winnerType)) {
//对boolean处理
if (!boolean.class.equals(candidateType)) {
isAmbiguous = true;
break;
} else if (candidate.getName().startsWith("is")) {
winner = candidate;
}
} else if (candidateType.isAssignableFrom(winnerType)) {
// OK getter type is descendant
//当前最适合的方法的返回佳是当前方法返回的子类,什么都不做,当前最适合的方法 依然不变
} else if (winnerType.isAssignableFrom(candidateType)) {
//当前方法的返回位是当前最适合的方法的返回值的子类,更新临时交量getter,当前的getter 方法成为最适合的getter 方法
winner = candidate;
} else {
//返回值相同,二义性,抛出异常
isAmbiguous = true;
break;
}
}
//添加到getMethods 集合并填充get Types 集合
addGetMethod(propName, winner, isAmbiguous);
}
}
/**
* 添加字段
* @param clazz
*/
private void addFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//当setMethods 集合不包含同名属性时,将其记录到setMethods 集合和set Types 集合
if (!setMethods.containsKey(field.getName())) {
// issue #379 - removed the check for final because JDK 1.5 allows
// modification of final fields through reflection (JSR-133). (JGB)
// pr #16 - final static can only be set by the classloader
int modifiers = field.getModifiers();
//过滤掉final和static 修饰的字段
if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
addSetField(field);
}
}
//当getMethods 集合中不包含同名属性时,将其记录到getMethods 集合和getTypes 集合
if (!getMethods.containsKey(field.getName())) {
addGetField(field);
}
}
if (clazz.getSuperclass() != null) {
//处理父类中定义的字段
addFields(clazz.getSuperclass());
}
}
}
添加方法的时候,会转成invoke类型
四个实现类,分别对应方法,字段
@Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
//返回字段值
return field.get(target);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}
/**
* 对Reflector 对象的创建和缓存
*/
public interface ReflectorFactory {
//检测该ReflectorFactory对象是否会缓存Reflector对象
boolean isClassCacheEnabled();
//设置是否缓存Reflector 对象
void setClassCacheEnabled(boolean classCacheEnabled);
//创建指定Class 对应的Reflector 对象
Reflector findForClass(Class<?> type);
}
public class DefaultReflectorFactory implements ReflectorFactory {
//该字段决定是否开启对Reflector 对象的缓存
private boolean classCacheEnabled = true;
//使用ConcurrentMap 集合实现对Reflector 对象的缓存
private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<>();
@Override
public Reflector findForClass(Class<?> type) {
//检测是否开启缓存
if (classCacheEnabled) {
// synchronized (type) removed see issue #461
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
//未开启缓存,则直接创建并返回Reflector对象
return new Reflector(type);
}
}
}
public interface ObjectFactory {
//设置配置信息
default void setProperties(Properties properties) {
// NOP
}
//通过无参构造器创建指定类的对象
<T> T create(Class<T> type);
//根据参数列表,从指定类型中选择合适的构造器创建对象
<T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs);
//检测指定类型是否为集合类型,主妥处理java.util.Collection 及其子类
<T> boolean isCollection(Class<T> type);
}
public class DefaultObjectFactory implements ObjectFactory, Serializable {
private static final long serialVersionUID = -8855120656740914948L;
public <T> T create(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
Class<?> classToCreate = resolveInterface(type);
// we know types are assignable
return (T) instantiateClass(classToCreate, constructorArgTypes, constructorArgs);
}
private <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
try {
Constructor<T> constructor;
//通过无参构造函数创建对象
if (constructorArgTypes == null || constructorArgs == null) {
constructor = type.getDeclaredConstructor();
try {
return constructor.newInstance();
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
constructor.setAccessible(true);
return constructor.newInstance();
} else {
throw e;
}
}
}
//根据指定的参数列表查找构造函数,并实例化对象
constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
try {
return constructor.newInstance(constructorArgs.toArray(new Object[0]));
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
constructor.setAccessible(true);
return constructor.newInstance(constructorArgs.toArray(new Object[0]));
} else {
throw e;
}
}
} catch (Exception e) {
String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
.stream().map(Class::getSimpleName).collect(Collectors.joining(","));
String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
.stream().map(String::valueOf).collect(Collectors.joining(","));
throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
}
}
}
/*
解析这样的格式orders[O].items[1].name
继承了迭代器,所以可以重复解析
resultMap>
*/
public class PropertyTokenizer implements Iterator<PropertyTokenizer> {
//当前表达式的名称
private String name;
//当前表达式的索引名
private final String indexedName;
//索引下标
private String index;
//子表达式
private final String children;
public PropertyTokenizer(String fullname) {
//查找”.”的位置
int delim = fullname.indexOf('.');
if (delim > -1) {
//初始化name
name = fullname.substring(0, delim);
//初始化children
children = fullname.substring(delim + 1);
} else {
name = fullname;
children = null;
}
//初始化indexedName
indexedName = name;
delim = name.indexOf('[');
if (delim > -1) {
//初始化index
index = name.substring(delim + 1, name.length() - 1);
name = name.substring(0, delim);
}
}
}
/**
* 方法名转换以及检测是否get/set
* @author Clinton Begin
*/
public final class PropertyNamer {
private PropertyNamer() {
// Prevent Instantiation of Static Class
}
//将方法名转换成属性名
public static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
name = name.substring(3);
} else {
throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
//检测方法名是否对应属性名
public static boolean isProperty(String name) {
return isGetter(name) || isSetter(name);
}
//检测方法是否为getter方法
public static boolean isGetter(String name) {
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
}
//检测方法是否为setter方法
public static boolean isSetter(String name) {
return name.startsWith("set") && name.length() > 3;
}
}
public final class PropertyCopier {
private PropertyCopier() {
// Prevent Instantiation of Static Class
}
public static void copyBeanProperties(Class<?> type, Object sourceBean, Object destinationBean) {
Class<?> parent = type;
while (parent != null) {
final Field[] fields = parent.getDeclaredFields();
for (Field field : fields) {
try {
try {
field.set(destinationBean, field.get(sourceBean));
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
//将sourceBean对象中的属性值设置到destinationBean对象中
field.set(destinationBean, field.get(sourceBean));
} else {
throw e;
}
}
} catch (Exception e) {
// Nothing useful to do, will only fail on final fields, which will be ignored.
}
}
//继续拷贝父类中定义的字段
parent = parent.getSuperclass();
}
}
}
/**
* 通过Reflector 和PropertyTokenizer组合使用
* 对复杂的属性表达式的解析
* 并实现了获取指定属性描述信息的功能。
* @author Clinton Begin
*/
public class MetaClass {
private final ReflectorFactory reflectorFactory;
//在创建MetaClass 时会指定一个类,该Reflector 对象会用于记录该类相关的元信息
private final Reflector reflector;
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
public String findProperty(String name) {
StringBuilder prop = buildProperty(name, new StringBuilder());
return prop.length() > 0 ? prop.toString() : null;
}
private StringBuilder buildProperty(String name, StringBuilder builder) {
//解析属性表达式
PropertyTokenizer prop = new PropertyTokenizer(name);
//是否还有子表达式
if (prop.hasNext()) {
//查找PropertyTokenizer.name对应的属性
String propertyName = reflector.findPropertyName(prop.getName());
if (propertyName != null) {
//追加属性名
builder.append(propertyName);
builder.append(".");
//为该属性创建对应的MetaClass 对象
MetaClass metaProp = metaClassForProperty(propertyName);
//递归解析PropertyTokenizer.children字段,并将解析结果添加到builder中保存
metaProp.buildProperty(prop.getChildren(), builder);
}
} else {
//递归出口
String propertyName = reflector.findPropertyName(name);
if (propertyName != null) {
builder.append(propertyName);
}
}
return builder;
}
public boolean hasGetter(String name) {
PropertyTokenizer prop = new PropertyTokenizer(name);
if (prop.hasNext()) {
//PropertyTokenizer.narne 指定的属性有getter 方法,才能处理子表达式
if (reflector.hasGetter(prop.getName())) {
MetaClass metaProp = metaClassForProperty(prop);
return metaProp.hasGetter(prop.getChildren());
} else {
return false;
}
} else {
return reflector.hasGetter(prop.getName());
}
}
private MetaClass metaClassForProperty(PropertyTokenizer prop) {
//获取表达式所表示的属性的类型
Class<?> propType = getGetterType(prop);
return MetaClass.forClass(propType, reflectorFactory);
}
private Class<?> getGetterType(PropertyTokenizer prop) {
//获取属性类型
Class<?> type = reflector.getGetterType(prop.getName());
//该表达式中是否使用” [] ” 指定了下标, 且是Collection 子类
if (prop.getIndex() != null && Collection.class.isAssignableFrom(type)) {
//通过TypeParameterResolver 工具类解析属性的类型
Type returnType = getGenericGetterType(prop.getName());
//针对ParameterizedType 进行处理, 针对泛型集合类型进行处理
if (returnType instanceof ParameterizedType) {
//获取实际的类型参数
Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments();
if (actualTypeArguments != null && actualTypeArguments.length == 1) {
//泛型的类型
returnType = actualTypeArguments[0];
if (returnType instanceof Class) {
type = (Class<?>) returnType;
} else if (returnType instanceof ParameterizedType) {
type = (Class<?>) ((ParameterizedType) returnType).getRawType();
}
}
}
}
return type;
}
private Type getGenericGetterType(String propertyName) {
try {
//根据Reflector . getMethods 集合中记录的Invoker 实现类的类型,决定解析getter 方法返回值
//类型还是解析字段类型
Invoker invoker = reflector.getGetInvoker(propertyName);
if (invoker instanceof MethodInvoker) {
Field declaredMethod = MethodInvoker.class.getDeclaredField("method");
declaredMethod.setAccessible(true);
Method method = (Method) declaredMethod.get(invoker);
return TypeParameterResolver.resolveReturnType(method, reflector.getType());
} else if (invoker instanceof GetFieldInvoker) {
Field declaredField = GetFieldInvoker.class.getDeclaredField("field");
declaredField.setAccessible(true);
Field field = (Field) declaredField.get(invoker);
return TypeParameterResolver.resolveFieldType(field, reflector.getType());
}
} catch (NoSuchFieldException | IllegalAccessException e) {
// Ignored
}
return null;
}
/**
* 是对对象的包装,抽象了对象的属性信息,它定义了一系列查
* 询对象属性信息的方法,以及更新属性的方法。
* @author Clinton Begin
*/
public interface ObjectWrapper {
// 如采Object Wrapper 中封装的是普通的Bean 对象,则调用相应属性的相应getter 方法,
// 如采封装的是集合类,则获取指定key 或下标对应的value 位
Object get(PropertyTokenizer prop);
void set(PropertyTokenizer prop, Object value);
// 查找属性表达式指定的属性,第二个参数表示是否忽略属性表达式中的下画线
String findProperty(String name, boolean useCamelCaseMapping);
// 查找可读属性的名称集合
String[] getGetterNames();
//查找可写属性的名称集合
String[] getSetterNames();
//解析属性表达式指定属性的setter 方法的参数类型
Class<?> getSetterType(String name);
//解析属性表达式指定属性的getter 方法的返回值类型
Class<?> getGetterType(String name);
boolean hasSetter(String name);
boolean hasGetter(String name);
// 为属性表达式指定的属性创建相应的MetaObject 对象
MetaObject instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory);
// 封装的对象是否为C o lle ction 类型
boolean isCollection();
// 调用Collection 对象的add ()方法
void add(Object element);
// 调用Co lle ction 对象的addAll ()方法
<E> void addAll(List<E> element);
}
public class BeanWrapper extends BaseWrapper {
@Override
public Object get(PropertyTokenizer prop) {
//存在索引信息,则表示属性表达式中的name 部分为集合类型
if (prop.getIndex() != null) {
// 通过MetaObject.getValue()方法获取object对象中的指定集合属性
Object collection = resolveCollection(prop, object);
return getCollectionValue(prop, collection);
} else {
//不存在索引信息,则name 部分为普通对象,查找并调用Invoker 相关方法获取属性
return getBeanProperty(prop, object);
}
}
protected Object getCollectionValue(PropertyTokenizer prop, Object collection) {
//如果是Map类型,则index为key
if (collection instanceof Map) {
return ((Map) collection).get(prop.getIndex());
} else {
//如采是其他集合类型,则index 为下标
int i = Integer.parseInt(prop.getIndex());
if (collection instanceof List) {
return ((List) collection).get(i);
} else if (collection instanceof Object[]) {
return ((Object[]) collection)[i];
} else if (collection instanceof char[]) {
return ((char[]) collection)[i];
} else if (collection instanceof boolean[]) {
return ((boolean[]) collection)[i];
} else if (collection instanceof byte[]) {
return ((byte[]) collection)[i];
} else if (collection instanceof double[]) {
return ((double[]) collection)[i];
} else if (collection instanceof float[]) {
return ((float[]) collection)[i];
} else if (collection instanceof int[]) {
return ((int[]) collection)[i];
} else if (collection instanceof long[]) {
return ((long[]) collection)[i];
} else if (collection instanceof short[]) {
return ((short[]) collection)[i];
} else {
throw new ReflectionException("The '" + prop.getName() + "' property of " + collection + " is not a List or Array.");
}
}
}
}
/**
* 解析属性表达式
* @author Clinton Begin
*/
public class MetaObject {
//原始JavaBean对象
private final Object originalObject;
//其中封装了originalObject,以及MetaObject对象
private final ObjectWrapper objectWrapper;
//负责实例化originalObject 的工厂对象
private final ObjectFactory objectFactory;
//负责创建ObjectWrapper 的工厂对象
private final ObjectWrapperFactory objectWrapperFactory;
// 用于创建并缓存Reflector 对象的工厂对象
private final ReflectorFactory reflectorFactory;
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
//若ObjectWrapperFactory 能够为该原始对象创建对应的ObjectWrapper 对象,则由优先使用ObjectWrapperFactory
//而DefaultObjectWrapperFactory.hasWrapperFor ()始终
//返回false 。用户可以自定义ObjectWrapperFactory 实现进行扩展
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
// 若object 为null ,则统一返回SystemMetaObject.NULL_META_OBJECT 这个标志对象
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
}
/**
* java类型 <=>SQL数据类型
* @author Clinton Begin
*/
public interface TypeHandler<T> {
//在通过PreparedStatement 为SQL 语句绑定参数时,会将数据由JdbcType 类型转换成Java 类型
void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
/**
* Gets the result.
*
* @param rs
* the rs
* @param columnName
* Colunm name, when configuration useColumnLabel
is false
* @return the result
* @throws SQLException
* the SQL exception
*/
//从ResultSet 中获取数据时会调用此方法,会将数据由Java 类型转换成JdbcType 类型
T getResult(ResultSet rs, String columnName) throws SQLException;
T getResult(ResultSet rs, int columnIndex) throws SQLException;
T getResult(CallableStatement cs, int columnIndex) throws SQLException;
}
/**
* 管理TypeHandler
* @author Clinton Begin
* @author Kazuki Shimizu
*/
public final class TypeHandlerRegistry {
// 记录JdbcType 与TypeHandler 之间的对应关系,其中JdbcType 是一个枚举类型,它定义对应的J DBC 类型
//该集合主要用于从结果集读取数据时,将数据从Jdbc 类型转换成Java 类型
private final Map<JdbcType, TypeHandler<?>> jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);
// 记录了Java 类型向指定JdbcType 转换时,需妥使用的TypeHandler 对象。例如: Java 类型中的String 可能
//转换成数据库的char 、varchar 等多种类型,所以存在一对多关系
private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();
private final TypeHandler<Object> unknownTypeHandler;
// 记录了全部TypeHandler 的类型以及该类型相应的T ypeHandler 对象
private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();
//空TypeHandler 集合的标识
private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();
// register ()方法的重载1的实现如下:
public void register(Class<?> typeHandlerClass) {
boolean mappedTypeFound = false;
//获取@MappedTypes主解
//@MappedTypes 注解用于指明该TypeHandler实现类能够处理的Java 类型的集合
MappedTypes mappedTypes = typeHandlerClass.getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
//根据@ MappedTypes i主解中指定的Java 类型进行注册
for (Class<?> javaTypeClass : mappedTypes.value()) {
register(javaTypeClass, typeHandlerClass);
mappedTypeFound = true;
}
}
if (!mappedTypeFound) {
//未指定@ MappedTypes 注解,交由重载2继续处理
register(getInstance(null, typeHandlerClass));
}
}
//register ()方法的重载2的实现如下:
public <T> void register(TypeHandler<T> typeHandler) {
boolean mappedTypeFound = false;
//获取@ MappedTypes 注解,并根据自MappedTypes 注解指定的Java 类型进行注册,逻辑与重载1类似
MappedTypes mappedTypes = typeHandler.getClass().getAnnotation(MappedTypes.class);
if (mappedTypes != null) {
for (Class<?> handledType : mappedTypes.value()) {
//交由重载3处理
register(handledType, typeHandler);
mappedTypeFound = true;
}
}
// @since 3.1.0 - try to auto-discover the mapped type
//从3 . 1. 0 版本开始,可以根据Type Handler 类型自动查找对应的Java 类型,这需妥
//我们的TypeHandler 实现类同时继承Type Reference 这个抽象类
if (!mappedTypeFound && typeHandler instanceof TypeReference) {
try {
TypeReference<T> typeReference = (TypeReference<T>) typeHandler;
//交由重载3处理
register(typeReference.getRawType(), typeHandler);
mappedTypeFound = true;
} catch (Throwable t) {
// maybe users define the TypeReference with a different type and are not assignable, so just ignore it
}
}
if (!mappedTypeFound) {
register((Class<T>) null, typeHandler);
}
}
// register ()方法的重载3的实现如下:
private <T> void register(Type javaType, TypeHandler<? extends T> typeHandler) {
//获取@ MappedJdbcTypes j主解
//指明该TypeHandler 实现类能够处理的JDBC 类型集合。
MappedJdbcTypes mappedJdbcTypes = typeHandler.getClass().getAnnotation(MappedJdbcTypes.class);
if (mappedJdbcTypes != null) {
for (JdbcType handledJdbcType : mappedJdbcTypes.value()) {
// 交由重载4完成注册
register(javaType, handledJdbcType, typeHandler);
}
if (mappedJdbcTypes.includeNullJdbcType()) {
// 交由重载4完成注册
register(javaType, null, typeHandler);
}
} else {
// 交由重载4完成注册
register(javaType, null, typeHandler);
}
}
//register ()方法的重载4的实现如下:
private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler) {
//检测是否明确指定了TypeHandler 能够处理的Java 类型
if (javaType != null) {
//获取指定Java 类型在TYPE HANDLER MAP 集合中对应的TypeHandler 集合
Map<JdbcType, TypeHandler<?>> map = typeHandlerMap.get(javaType);
// 创建新的TypeHandler 集合,并添加到typeHandlerMap中
if (map == null || map == NULL_TYPE_HANDLER_MAP) {
map = new HashMap<>();
}
//将TypeHandler 对象注册到typeHandlerMap集合
map.put(jdbcType, handler);
typeHandlerMap.put(javaType, map);
}
//向allTypeHandlersMap集合注册TypeHandler 类型和对应的TypeHandler 对象
allTypeHandlersMap.put(handler.getClass(), handler);
}
//register ()方法的重载5的实现如下:
public void register(JdbcType jdbcType, TypeHandler<?> handler) {
//注册JDBC 类型对应的Type Handler
jdbcTypeHandlerMap.put(jdbcType, handler);
}
//下面是register ()方法的重载⑥的实现, 主要用来自动扫描指定包下的TypeHandler实现类并完成注册
public void register(String packageName) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
//查找指定包下的Type Handler 接口实现类
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
for (Class<?> type : handlerSet) {
//Ignore inner classes and interfaces (including package-info.java) and abstract classes
//过滤掉内部类、接口以及抽象类
if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
//交由重载1继续后续注册操作
register(type);
}
}
}
/**
* 根据指定的Java类型和JdbcType 类型查找相应的TypeHandler对象,
* @param type
* @return
*/
private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
if (ParamMap.class.equals(type)) {
return null;
}
//查找(或初始化) Java 类型对应的TypeHandler集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
// 根据JdbcType 类型查找TypeHandler 对象
handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
if (handler == null) {
// #591
//如果jdbcHandlerMap 只注册了一个Type Handler ,则使用此TypeHandler 对象
handler = pickSoleHandler(jdbcHandlerMap);
}
}
// type drives generics here
return (TypeHandler<T>) handler;
}
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
//查找指定Java 类型对应的TypeHandler 集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
//检测是否为空集合标识
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
return null;
}
//初始化指定Java 类型的T ypeHandler 集合
if (jdbcHandlerMap == null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
//枚举类型的处理
if (Enum.class.isAssignableFrom(clazz)) {
Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
if (jdbcHandlerMap == null) {
register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
return typeHandlerMap.get(enumClass);
}
} else {
//查找父类对应的TypeHandler 集合,并作为初始集合
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
}
}
typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
return jdbcHandlerMap;
}
}
/**
* 扫描指定包下所有的类并为指定类的子类添加别名:
* 读取@Alias注解
* @param packageName
* @param superType
*/
public void registerAliases(String packageName, Class<?> superType) {
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
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);
}
}
}
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 (typeAliases.containsKey(key) && typeAliases.get(key) != null && !typeAliases.get(key).equals(value)) {
throw new TypeException("The alias '" + alias + "' is already mapped to the value '" + typeAliases.get(key).getName() + "'.");
}
typeAliases.put(key, value);
}
public final class LogFactory {
/**
* Marker to be used by logging implementations that support markers.
*/
public static final String MARKER = "MYBATIS";
// 记录当前使用的第二方日志组件所对应的适配器的构造方法
private static Constructor<? extends Log> logConstructor;
static {
//下面会针对每种日志组件调用tr yimplementation ( )方法进行尝试加载,具体调用顺序是:
//useSlf4jLogging ()一> useCommonsLogging ()一> useLog4J2Logging ()一〉
// useLog 4JLogging()--> useJdkLogging() -> useNoLogging()
tryImplementation(LogFactory::useSlf4jLogging);
tryImplementation(LogFactory::useCommonsLogging);
tryImplementation(LogFactory::useLog4J2Logging);
tryImplementation(LogFactory::useLog4JLogging);
tryImplementation(LogFactory::useJdkLogging);
tryImplementation(LogFactory::useNoLogging);
}
public static synchronized void useJdkLogging() {
setImplementation(org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl.class);
}
private static void setImplementation(Class<? extends Log> implClass) {
try {
//获取指定适配器的构造方法
Constructor<? extends Log> candidate = implClass.getConstructor(String.class);
//实例化运配葛
Log log = candidate.newInstance(LogFactory.class.getName());
if (log.isDebugEnabled()) {
log.debug("Logging initialized using '" + implClass + "' adapter.");
}
logConstructor = candidate;
} catch (Throwable t) {
throw new LogException("Error setting Log implementation. Cause: " + t, t);
}
}
}
public class Jdk14LoggingImpl implements Log {
//底层封笨的〕ava .util .logging .Logger 对象
private final Logger log;
// 初始化java .util.logging .Logger 对象
public Jdk14LoggingImpl(String clazz) {
log = Logger.getLogger(clazz);
}
@Override
//将请求全部委托给了java.util.logg 工ng . Logger 对象的相应方法
public void error(String s, Throwable e) {
log.log(Level.SEVERE, s, e);
}
}
public abstract class BaseJdbcLogger {
// 记录了PreparedStateme接口中定义的常用的set*()方法
protected static final Set<String> SET_METHODS;
// 记录了Statement 接口和PreparedStatement 接口中与执行SQL 语句相关的方法
protected static final Set<String> EXECUTE_METHODS = new HashSet<>();
private final Map<Object, Object> columnMap = new HashMap<>();
//记录了PreparedStatement . set *()方法设置的key 位
private final List<Object> columnNames = new ArrayList<>();
//记录了PreparedStatement . set *()方法设置的value 值
private final List<Object> columnValues = new ArrayList<>();
// 用于输出日志的Log 对象
protected final Log statementLog;
// 记录了SQL 的层数, 用于格式化输出SQL
protected final int queryStack;
}
public final class ConnectionLogger extends BaseJdbcLogger implements InvocationHandler {
public static Connection newInstance(Connection conn, Log statementLog, int queryStack) {
//使用JDK 动态代理的方式创建代理对象
InvocationHandler handler = new ConnectionLogger(conn, statementLog, queryStack);
ClassLoader cl = Connection.class.getClassLoader();
return (Connection) Proxy.newProxyInstance(cl, new Class[]{Connection.class}, handler);
}
@Override
public Object invoke(Object proxy, Method method, Object[] params)
throws Throwable {
try {
//如调用的是从Object继承的方法,则直接调用,不做任何其他处理
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
//如果调用的是prepareStatement ()方法、prepareCall ()方法或createStatement()方法,
//则在创建相应Statement 对象后,为其创建代理对象并返回该代理对象
if ("prepareStatement".equals(method.getName()) || "prepareCall".equals(method.getName())) {
// 日志输出
if (isDebugEnabled()) {
debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);
}
PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);
//为该PreparedStatement 对象创建代理对象
stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else if ("createStatement".equals(method.getName())) {
Statement stmt = (Statement) method.invoke(connection, params);
stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);
return stmt;
} else {
return method.invoke(connection, params);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
public final class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
//调用了EXECUTE_METHODS集合中的方法
if (EXECUTE_METHODS.contains(method.getName())) {
if (isDebugEnabled()) {
// 日志输出,输出的是参数值以及参数类型
debug("Parameters: " + getParameterValueString(), true);
}
// 清空BaseJdbcLogger 中定义的三个column *集合
clearColumnInfo();
if ("executeQuery".equals(method.getName())) {
//如果调用executeQuery ()方法, 则为ResultSet 创建代理对象
ResultSet rs = (ResultSet) method.invoke(statement, params);
return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
} else {
return method.invoke(statement, params);
}
} else if (SET_METHODS.contains(method.getName())) {
//如果调用SET_METHODS 集合中的方法, 则通过setColumn ()方法记录到BaseJdbcLogger 中定义的三个column *集合
if ("setNull".equals(method.getName())) {
setColumn(params[0], null);
} else {
setColumn(params[0], params[1]);
}
return method.invoke(statement, params);
} else if ("getResultSet".equals(method.getName())) {
//如果调用getResultSet ()方法,则为ResultSet创建代理对象
ResultSet rs = (ResultSet) method.invoke(statement, params);
return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
} else if ("getUpdateCount".equals(method.getName())) {
//如果调用getUpdateCount ( )方法,则通过日志框架输出其结果
int updateCount = (Integer) method.invoke(statement, params);
if (updateCount != -1) {
debug(" Updates: " + updateCount, false);
}
return updateCount;
} else {
return method.invoke(statement, params);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
public final class ResultSetLogger extends BaseJdbcLogger implements InvocationHandler {
// 记录了超大长度的类型
private static final Set<Integer> BLOB_TYPES = new HashSet<>();
// 是否是ResultSet 结采集的第一行
private boolean first = true;
// 统计行数
private int rows;
// 真正的ResultSet 对象
private final ResultSet rs;
// 记录了起大字段的列编号
private final Set<Integer> blobColumns = new HashSet<>();
@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, params);
}
Object o = method.invoke(rs, params);
//针对ResultSet.next ()方法的处理
if ("next".equals(method.getName())) {
//是否还存在下一行数据
if ((Boolean) o) {
rows++;
if (isTraceEnabled()) {
ResultSetMetaData rsmd = rs.getMetaData();
//获取数据集的列数
final int columnCount = rsmd.getColumnCount();
//如采是第一行数据,则输出表头
if (first) {
first = false;
//除了输出农头,还会填充blobColurnns 集合,记录超大类型的列
printColumnHeaders(rsmd, columnCount);
}
//输出该H记录,注意会过滤掉blobColurnns 中记录的列,这些列的数据较大,不会输出到日志
printColumnValues(columnCount);
}
} else {
//边历完ResultSet 之后,会输出总函数
debug(" Total: " + rows, false);
}
}
// 清空BaseJdbcLogger 中的column *集合
clearColumnInfo();
return o;
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
/**
* 会按照指定的顺序依次检测其中封装的ClassLoader 对象,并从中选取第一
* 个可用的ClassLoader 完成相关功能。
* A class to wrap access to multiple class loaders making them work as one
*
* @author Clinton Begin
*/
public class ClassLoaderWrapper {
// 应用指定的默认类加载器
ClassLoader defaultClassLoader;
// System ClassLoader
ClassLoader systemClassLoader;
ClassLoaderWrapper() {
try {
//初始化systemClassLoader 字段
systemClassLoader = ClassLoader.getSystemClassLoader();
} catch (SecurityException ignored) {
// AccessControlException on Google App Engine
}
}
public URL getResourceAsURL(String resource, ClassLoader classLoader) {
return getResourceAsURL(resource, getClassLoaders(classLoader));
}
URL getResourceAsURL(String resource, ClassLoader[] classLoader) {
URL url;
// 遍历ClassLoader 数纽
for (ClassLoader cl : classLoader) {
if (null != cl) {
//调用ClassLoader.getResource ()方法查找指定的资源
// look for the resource as passed in...
url = cl.getResource(resource);
// ...but some class loaders want this leading "/", so we'll add it
// and try again if we didn't find the resource
if (null == url) {
//尝试以” / ”开头,再次查找
url = cl.getResource("/" + resource);
}
// "It's always in the last place I look for it!"
// ... because only an idiot would keep looking for it after finding it, so stop looking already.
//查找到指定的资源
if (null != url) {
return url;
}
}
}
// didn't find it anywhere.
return null;
}
/**
* 返回Class Loader[]数组,该数组指明了类加载器的使用顺序
* @param classLoader
* @return
*/
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
//参数指定的类加载器
classLoader,
//系统指定的默认类加载器
defaultClassLoader,
// 当前线程绑定的类加载器
Thread.currentThread().getContextClassLoader(),
// 加载当前类所使用的类加载器
getClass().getClassLoader(),
//System Cl assLoader
systemClassLoader};
}
}
// 根据指定的条件查找指定包下的类
public class ResolverUtil<T> {
/**
* A simple interface that specifies how to test classes to determine if they
* are to be included in the results produced by the ResolverUtil.
*/
public interface Test {
/**
* Will be called repeatedly with candidate classes. Must return True if a class
* is to be included in the results, false otherwise.
* 如果该类符合检测的条件,则matches ()方法返回true ,否则返回false
* @param type 待检测的类
* the type
* @return true, if successful
*/
boolean matches(Class<?> type);
}
/**
* A Test that checks to see if each class is assignable to the provided class. Note
* that this test will match the parent type itself if it is presented for matching.
* 检测类是否继承了指定的类或接口
*/
public static class IsA implements Test {}
/**
* A Test that checks to see if each class is annotated with a specific annotation. If it
* is, then the test returns true, otherwise false.
*
* 检测类是否添加了指定的注解
*/
public static class AnnotatedWith implements Test {}
public ResolverUtil<T> find(Test test, String packageName) {
//根据包名获取其对应的路径
String path = getPackagePath(packageName);
try {
//查找packageName 包下的所有资源
List<String> children = VFS.getInstance().list(path);
for (String child : children) {
if (child.endsWith(".class")) {
// 检测该类是否符合test 条件
addIfMatching(test, child);
}
}
} catch (IOException ioe) {
log.error("Could not read package: " + packageName, ioe);
}
return this;
}
protected void addIfMatching(Test test, String fqn) {
try {
// fqn 是类的完全限定名,即包括其所在包的包名
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);
//通过Test.matches ()方法检测条件是否满足
if (test.matches(type)) {
//将符合条件的类记录到matches 集合中
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());
}
}
/**
* Returns the classloader that will be used for scanning for classes. If no explicit
* ClassLoader has been set by the calling, the context class loader will be used.
*
* @return the ClassLoader that will be used to scan for classes
*
* 默认获取当前线程类加载器,可通过setClassLoader提前设置类加载器
*/
public ClassLoader getClassLoader() {
return classloader == null ? Thread.currentThread().getContextClassLoader() : classloader;
}
}
/**
* Provides a very simple API for accessing resources within an application server.
* 表示虚拟文件系统( Virtual File System ) , 它用来查找指定路径下的资源。
* @author Ben Gunter
*/
public abstract class VFS {
//羊例模式,记录了全局唯一的VFS 对象
private static class VFSHolder {
static final VFS INSTANCE = createVFS();
@SuppressWarnings("unchecked")
static VFS createVFS() {
// Try the user implementations first, then the built-ins
// 优先使用用户自定义的VFS 实现, 如没有自定义VFS 实现,则使用MyBatis 提供的VFS 实现
List<Class<? extends VFS>> impls = new ArrayList<>();
impls.addAll(USER_IMPLEMENTATIONS);
impls.addAll(Arrays.asList((Class<? extends VFS>[]) IMPLEMENTATIONS));
// Try each implementation class until a valid one is found
//遍历集合,依次实例化VFS 对象并检测VFS 对象是否有效,一旦得到有效的VFS 对象,则结束循环
VFS vfs = null;
for (int i = 0; vfs == null || !vfs.isValid(); i++) {
Class<? extends VFS> impl = impls.get(i);
try {
vfs = impl.getDeclaredConstructor().newInstance();
if (!vfs.isValid() && log.isDebugEnabled()) {
log.debug("VFS implementation " + impl.getName()
+ " is not valid in this environment.");
}
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
log.error("Failed to instantiate " + impl, e);
return null;
}
}
if (log.isDebugEnabled()) {
log.debug("Using VFS adapter " + vfs.getClass().getName());
}
return vfs;
}
}
/**
* Get the singleton {@link VFS} instance. If no {@link VFS} implementation can be found for the current environment,
* then this method returns null.
*
* @return single instance of VFS
*/
public static VFS getInstance() {
return VFSHolder.INSTANCE;
}
}
public class DefaultVFS extends VFS {
@Override
/**
* 责检测当前VFS 对象
* 在当前环境下是否有效,
*/
public boolean isValid() {
return true;
}
@Override
/**
* 查找指定的资源名称列表
*/
public List<String> list(URL url, String path) throws IOException {
InputStream is = null;
try {
List<String> resources = new ArrayList<>();
// First, try to find the URL of a JAR file containing the requested resource. If a JAR
// file is found, then we'll list child resources by reading the JAR.
//如果url 指向的资源在一个Jar 包中,则获取该Jar 包对应的URL ,否则返回n ull
URL jarUrl = findJarForResource(url);
if (jarUrl != null) {
is = jarUrl.openStream();
if (log.isDebugEnabled()) {
log.debug("Listing " + url);
}
//遍历Jar 中的资源,并返回以path 开头的资源列表
resources = listResources(new JarInputStream(is), path);
} else {
//遍历url 指向的目录,将其下资源名称记录到c hildren 集合中
List<String> children = new ArrayList<>();
try {
if (isJar(url)) {
// Some versions of JBoss VFS might give a JAR stream even if the resource
// referenced by the URL isn't actually a JAR
is = url.openStream();
try (JarInputStream jarInput = new JarInputStream(is)) {
if (log.isDebugEnabled()) {
log.debug("Listing " + url);
}
for (JarEntry entry; (entry = jarInput.getNextJarEntry()) != null; ) {
if (log.isDebugEnabled()) {
log.debug("Jar entry: " + entry.getName());
}
children.add(entry.getName());
}
}
} else {
/*
* Some servlet containers allow reading from directory resources like a
* text file, listing the child resources one per line. However, there is no
* way to differentiate between directory and file resources just by reading
* them. To work around that, as each line is read, try to look it up via
* the class loader as a child of the current resource. If any line fails
* then we assume the current resource is not a directory.
*/
is = url.openStream();
List<String> lines = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
for (String line; (line = reader.readLine()) != null;) {
if (log.isDebugEnabled()) {
log.debug("Reader entry: " + line);
}
lines.add(line);
if (getResources(path + "/" + line).isEmpty()) {
lines.clear();
break;
}
}
}
if (!lines.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("Listing " + url);
}
children.addAll(lines);
}
}
} catch (FileNotFoundException e) {
/*
* For file URLs the openStream() call might fail, depending on the servlet
* container, because directories can't be opened for reading. If that happens,
* then list the directory directly instead.
*/
if ("file".equals(url.getProtocol())) {
File file = new File(url.getFile());
if (log.isDebugEnabled()) {
log.debug("Listing directory " + file.getAbsolutePath());
}
if (file.isDirectory()) {
if (log.isDebugEnabled()) {
log.debug("Listing " + url);
}
children = Arrays.asList(file.list());
}
} else {
// No idea where the exception came from so rethrow it
throw e;
}
}
// The URL prefix to use when recursively listing child resources
String prefix = url.toExternalForm();
if (!prefix.endsWith("/")) {
prefix = prefix + "/";
}
// Iterate over immediate children, adding files and recursing into directories
//遍历children 集合,递归查找符合条件的资源名称
for (String child : children) {
String resourcePath = path + "/" + child;
resources.add(resourcePath);
URL childUrl = new URL(prefix + child);
resources.addAll(list(childUrl, resourcePath));
}
}
return resources;
} finally {
if (is != null) {
try {
is.close();
} catch (Exception e) {
// Ignore
}
}
}
}
protected List<String> listResources(JarInputStream jar, String path) throws IOException {
// Include the leading and trailing slash when matching names
//如果path 不是以”/”开始和结束,则在其开始和结束位置添加”/”
if (!path.startsWith("/")) {
path = "/" + path;
}
if (!path.endsWith("/")) {
path = path + "/";
}
// Iterate over the entries and collect those that begin with the requested path
List<String> resources = new ArrayList<>();
//遍历整个Jar,将以path 开头的资源记录到resources 集合中并返回
for (JarEntry entry; (entry = jar.getNextJarEntry()) != null;) {
if (!entry.isDirectory()) {
// Add leading slash if it's missing
StringBuilder name = new StringBuilder(entry.getName());
if (name.charAt(0) != '/') {
name.insert(0, '/');
}
// Check file name
//检测name 是否以path 开头
if (name.indexOf(path) == 0) {
if (log.isDebugEnabled()) {
log.debug("Found resource: " + name);
}
// Trim leading slash
//记录资源、名称
resources.add(name.substring(1));
}
}
}
return resources;
}
}
/**
* @author Clinton Begin
*/
public interface DataSourceFactory {
//设置Data Source 的相关属性,一般紧跟在初始化完成之后
void setProperties(Properties props);
//获取DataSource 对象
DataSource getDataSource();
}
public class UnpooledDataSourceFactory implements DataSourceFactory {
public UnpooledDataSourceFactory() {
this.dataSource = new UnpooledDataSource();
}
@Override
public void setProperties(Properties properties) {
Properties driverProperties = new Properties();
//创建DataSource 相应的MetaObject
MetaObject metaDataSource = SystemMetaObject.forObject(dataSource);
//遍历properties 集合,该集合中设置了数据源需要的信息
for (Object key : properties.keySet()) {
String propertyName = (String) key;
if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {
String value = properties.getProperty(propertyName);
//以” driver . ”开头的配置项是对DataSource 的配置,记录到driverProperties 中保存
driverProperties.setProperty(propertyName.substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
} else if (metaDataSource.hasSetter(propertyName)) {
String value = (String) properties.get(propertyName);
//根据属性类型进行类型转换, 主要是Integer 、Long 、Boolean 三种类型的转换
Object convertedValue = convertValue(metaDataSource, propertyName, value);
//设置DataSource 的相关属性值
metaDataSource.setValue(propertyName, convertedValue);
} else {
throw new DataSourceException("Unknown DataSource property: " + propertyName);
}
}
//设置DataSource.driverProperties 属性值
if (driverProperties.size() > 0) {
metaDataSource.setValue("driverProperties", driverProperties);
}
}
}
public class UnpooledDataSource implements DataSource {
//加载Driver 类的类加载器
private ClassLoader driverClassLoader;
//数据库连接驱动的相关配置
private Properties driverProperties;
//缓存所有已注册的数据库连接驱动
private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<>();
//数据库连接的驱动名称
private String driver;
private String url;
private String username;
private String password;
// 是否自动提交
private Boolean autoCommit;
// 事务隔离级别
private Integer defaultTransactionIsolationLevel;
private Integer defaultNetworkTimeout;
static {
//将己在DriverManager 中注册的JDBC Driver 复制一份到UnpooledDataSource.registeredDrivers 集合中。
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
registeredDrivers.put(driver.getClass().getName(), driver);
}
}
private Connection doGetConnection(Properties properties) throws SQLException {
// 初始化数据库驱动
initializeDriver();
//创建真正的数据库连接
Connection connection = DriverManager.getConnection(url, properties);
//配置数据库连接的autoCommit 和隔离级别
configureConnection(connection);
return connection;
}
private synchronized void initializeDriver() throws SQLException {
//检测驱动是否已注册
if (!registeredDrivers.containsKey(driver)) {
Class<?> driverType;
try {
if (driverClassLoader != null) {
//注册驱动
driverType = Class.forName(driver, true, driverClassLoader);
} else {
driverType = Resources.classForName(driver);
}
// DriverManager requires the driver to be loaded via the system ClassLoader.
// http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
//创建Driver 对象
Driver driverInstance = (Driver) driverType.getDeclaredConstructor().newInstance();
//注册驱动, DriverProxy 是定义在UnpooledDataSource 中的内部类,是Driver 的静态代理类
DriverManager.registerDriver(new DriverProxy(driverInstance));
//将驱动添加到registeredDrivers 集合中
registeredDrivers.put(driver, driverInstance);
} catch (Exception e) {
throw new SQLException("Error setting driver on UnpooledDataSource. Cause: " + e);
}
}
}
private void configureConnection(Connection conn) throws SQLException {
if (defaultNetworkTimeout != null) {
conn.setNetworkTimeout(Executors.newSingleThreadExecutor(), defaultNetworkTimeout);
}
if (autoCommit != null && autoCommit != conn.getAutoCommit()) {
// 设置事务是否自动提交
conn.setAutoCommit(autoCommit);
}
if (defaultTransactionIsolationLevel != null) {
//设置事务隔离级别
conn.setTransactionIsolation(defaultTransactionIsolationLevel);
}
}
}
class PooledConnection implements InvocationHandler {
private static final String CLOSE = "close";
private static final Class<?>[] IFACES = new Class<?>[] { Connection.class };
private final int hashCode;
// 记录当前PooledConnecti对象所在的PooledDataSource 对象。该PooledConnection 是从
//该PooledDataSource 中获取的;当调用close ()方法时会将PooledConnection放回该PooledDataSource中
private final PooledDataSource dataSource;
// 真正的数据库连接
private final Connection realConnection;
// 数据库连接的代理对象
private final Connection proxyConnection;
// 从连接池中取出该连接的时间戳
private long checkoutTimestamp;
// 该连接创建的时间戳
private long createdTimestamp;
// 最后一次被使用的时间戳
private long lastUsedTimestamp;
// 由数据库URL 、用户名和密码计算出来的hash,可用于标识该连接所在的连接池
private int connectionTypeCode;
//检测当前PooledConnection 是否有效,主要是为了防止程序通过close ()方法将连接归还给连接池之后,依
//然通过该连接操作数据库
private boolean valid;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
//如果调用close ()方法,则将其重新放入连接池,而不是真正关闭数据库连接
if (CLOSE.equals(methodName)) {
dataSource.pushConnection(this);
return null;
}
try {
if (!Object.class.equals(method.getDeclaringClass())) {
// issue #579 toString() should never fail
// throw an SQLException instead of a Runtime
// 通过valid 字段检测连接是否有效
checkConnection();
}
// 调用真正数据库连接对象的对应方法
return method.invoke(realConnection, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
public class PoolState {
protected PooledDataSource dataSource;
// 空闲的PooledConnection 集合
protected final List<PooledConnection> idleConnections = new ArrayList<>();
// 活跃的PooledConnection 集合
protected final List<PooledConnection> activeConnections = new ArrayList<>();
// 请求数据库连接的次数
protected long requestCount = 0;
// 获取连接的累积时间
protected long accumulatedRequestTime = 0;
// checkoutTime 表示应用从连接池中取出连接,到归还连接这段时长,
// accumulatedCheckoutTime 记录了所有连接累积的checkout Time 时长
protected long accumulatedCheckoutTime = 0;
// 当连接长时间未归还给连接池时,会被认为该连接超时,
// claimedOverdueConnectionCount 记录了超时的连接个数
protected long claimedOverdueConnectionCount = 0;
// 累积超时时间
protected long accumulatedCheckoutTimeOfOverdueConnections = 0;
// 累积等待时间
protected long accumulatedWaitTime = 0;
// 等待次数
protected long hadToWaitCount = 0;
// 无效的连接数
protected long badConnectionCount = 0;
}
public class PooledDataSource implements DataSource {
private static final Log log = LogFactory.getLog(PooledDataSource.class);
//通过PoolState 管理连接池的状态并记录统计信息
private final PoolState state = new PoolState(this);
//记录Unpoo ledData Source 对象,用于生成真实的数据库连接对象,构造函数中会初始化该字段
private final UnpooledDataSource dataSource;
// OPTIONAL CONFIGURATION FIELDS
//最大活跃连接数
protected int poolMaximumActiveConnections = 10;
// 最大空闲连接数
protected int poolMaximumIdleConnections = 5;
// 最大checkout 时长
protected int poolMaximumCheckoutTime = 20000;
// 在无法获取连接时,线程需要等待的时间
protected int poolTimeToWait = 20000;
protected int poolMaximumLocalBadConnectionTolerance = 3;
// 在检测一个数据库连接是否可用时,会给数据库发送一个测试SQL 语句
protected String poolPingQuery = "NO PING QUERY SET";
// 是否允许发送测试SQL语句
protected boolean poolPingEnabled;
//当连接超过poolPingConnectionsNotUsedFor 毫秒未使用时,会发送一次测试SQL 语句,检测连接是否正常
protected int poolPingConnectionsNotUsedFor;
//根据数据库的URL 、用户名和密码生成的一个hash 佳,该哈希值用于标志着当前的连接池,在构造函数中初始化
private int expectedConnectionTypeCode;
private PooledConnection popConnection(String username, String password) throws SQLException {
boolean countedWait = false;
PooledConnection conn = null;
long t = System.currentTimeMillis();
int localBadConnectionCount = 0;
while (conn == null) {
//同步
synchronized (state) {
//检测空闲连接
if (!state.idleConnections.isEmpty()) {
// Pool has available connection
//获取连接
conn = state.idleConnections.remove(0);
if (log.isDebugEnabled()) {
log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
}
} else {
//当前连接池没有空闲连接
// 活跃连接数没有到最大值,则可以创建新连接
// Pool does not have available connection
if (state.activeConnections.size() < poolMaximumActiveConnections) {
// Can create new connection
//创建新数据库连接,并封装成PooledConnection 对象
conn = new PooledConnection(dataSource.getConnection(), this);
if (log.isDebugEnabled()) {
log.debug("Created connection " + conn.getRealHashCode() + ".");
}
} else {
//活跃连接数已到最大值,则不能创建新连接
//获取最先创建的活跃连接
// Cannot create new connection
PooledConnection oldestActiveConnection = state.activeConnections.get(0);
long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
//连接是否超时
if (longestCheckoutTime > poolMaximumCheckoutTime) {
// Can claim overdue connection
//对超时连接的信息进行统计
state.claimedOverdueConnectionCount++;
state.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
state.accumulatedCheckoutTime += longestCheckoutTime;
//将超时连接移出activeConnections集合
state.activeConnections.remove(oldestActiveConnection);
//如超时连接未提交,则自动回滚
if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
try {
oldestActiveConnection.getRealConnection().rollback();
} catch (SQLException e) {
/*
Just log a message for debug and continue to execute the following
statement like nothing happened.
Wrap the bad connection with a new PooledConnection, this will help
to not interrupt current executing thread and give current thread a
chance to join the next competition for another valid/good database
connection. At the end of this loop, bad {@link @conn} will be set as null.
*/
log.debug("Bad connection. Could not roll back");
}
}
//创建新PooledConnection对象,但是真正的数据库连接并未创建新的
conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
//将起时PooledConnection 设置为无效
oldestActiveConnection.invalidate();
if (log.isDebugEnabled()) {
log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
}
} else {
//无空闲连接、无法创建新连接且无超时连接,只能阻塞等待
// Must wait
try {
if (!countedWait) {
//统计等待次数
state.hadToWaitCount++;
countedWait = true;
}
if (log.isDebugEnabled()) {
log.debug("Waiting as long as " + poolTimeToWait + " milliseconds for connection.");
}
long wt = System.currentTimeMillis();
//阻塞等待
state.wait(poolTimeToWait);
//统计累积的等待时间
state.accumulatedWaitTime += System.currentTimeMillis() - wt;
} catch (InterruptedException e) {
break;
}
}
}
}
if (conn != null) {
// ping to server and check the connection is valid or not
//检测PooledConnect是否有效
if (conn.isValid()) {
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
//配置PooledConnection 的相关属性
conn.setConnectionTypeCode(assembleConnectionTypeCode(dataSource.getUrl(), username, password));
conn.setCheckoutTimestamp(System.currentTimeMillis());
conn.setLastUsedTimestamp(System.currentTimeMillis());
state.activeConnections.add(conn);
// 进行相关统计
state.requestCount++;
state.accumulatedRequestTime += System.currentTimeMillis() - t;
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") was returned from the pool, getting another connection.");
}
state.badConnectionCount++;
localBadConnectionCount++;
conn = null;
if (localBadConnectionCount > (poolMaximumIdleConnections + poolMaximumLocalBadConnectionTolerance)) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Could not get a good connection to the database.");
}
throw new SQLException("PooledDataSource: Could not get a good connection to the database.");
}
}
}
}
}
if (conn == null) {
if (log.isDebugEnabled()) {
log.debug("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
throw new SQLException("PooledDataSource: Unknown severe error condition. The connection pool returned a null connection.");
}
return conn;
}
protected void pushConnection(PooledConnection conn) throws SQLException {
//同步
synchronized (state) {
//移除该PooledConnection 对象
state.activeConnections.remove(conn);
//检测PooledConnection 对象是否有效
if (conn.isValid()) {
// 检测空闲连接数是否已达到上限,以及PooledConnection 是否为该连接池的连接
if (state.idleConnections.size() < poolMaximumIdleConnections && conn.getConnectionTypeCode() == expectedConnectionTypeCode) {
//累积checkout 时长
state.accumulatedCheckoutTime += conn.getCheckoutTime();
//回滚未提交的事务
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
//为返还连接创建新的PooledConnection 对象
PooledConnection newConn = new PooledConnection(conn.getRealConnection(), this);
//添加到idleConnections 集合
state.idleConnections.add(newConn);
newConn.setCreatedTimestamp(conn.getCreatedTimestamp());
newConn.setLastUsedTimestamp(conn.getLastUsedTimestamp());
//将原PooledConnection 对象设置为无效
conn.invalidate();
if (log.isDebugEnabled()) {
log.debug("Returned connection " + newConn.getRealHashCode() + " to pool.");
}
//唤醒阻塞等待的线程
state.notifyAll();
} else {
//空闲连接数已达到上限或PooledConnection 对象并不属于该连接池
// 累积checkout 时长
state.accumulatedCheckoutTime += conn.getCheckoutTime();
//回滚未提交的事务
if (!conn.getRealConnection().getAutoCommit()) {
conn.getRealConnection().rollback();
}
//关闭真正的数据库连接
conn.getRealConnection().close();
if (log.isDebugEnabled()) {
log.debug("Closed connection " + conn.getRealHashCode() + ".");
}
// 将PooledConnect 工on 对象设置为元效
conn.invalidate();
}
} else {
if (log.isDebugEnabled()) {
log.debug("A bad connection (" + conn.getRealHashCode() + ") attempted to return to the pool, discarding connection.");
}
// 统计元效PooledConnection 对象个敛
state.badConnectionCount++;
}
}
}
protected boolean pingConnection(PooledConnection conn) {
// 记录ping 操作是否成功
boolean result = true;
try {
// 检测真正的数据库连接是否已经关闭
result = !conn.getRealConnection().isClosed();
} catch (SQLException e) {
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
}
result = false;
}
//检测poolPingEnabled 设置,是否运行执行测试SQL 语句
// 长时间(超过poolPingConnectionsNotUsedFor 指定的时长)未使用的连接,才需要ping 操作来检测数据库连接是否正常
if (result && poolPingEnabled && poolPingConnectionsNotUsedFor >= 0
&& conn.getTimeElapsedSinceLastUse() > poolPingConnectionsNotUsedFor) {
try {
if (log.isDebugEnabled()) {
log.debug("Testing connection " + conn.getRealHashCode() + " ...");
}
Connection realConn = conn.getRealConnection();
try (Statement statement = realConn.createStatement()) {
statement.executeQuery(poolPingQuery).close();
}
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
result = true;
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is GOOD!");
}
} catch (Exception e) {
log.warn("Execution of ping query '" + poolPingQuery + "' failed: " + e.getMessage());
try {
conn.getRealConnection().close();
} catch (Exception e2) {
// ignore
}
result = false;
if (log.isDebugEnabled()) {
log.debug("Connection " + conn.getRealHashCode() + " is BAD: " + e.getMessage());
}
}
}
return result;
}
/* 当修改PooledDataSource 的字段时,
例如数据库URL 、用户名、密码、autoCornmit 配置等, 都会调用forceCloseAll()方法将所
有数据库连接关闭, 同时也会将所有相应的PooledConnection对象都设置为无效*/
public void forceCloseAll() {
synchronized (state) {
//更新当前连接池的标识
expectedConnectionTypeCode = assembleConnectionTypeCode(dataSource.getUrl(), dataSource.getUsername(), dataSource.getPassword());
// 处理全部的活跃连接
for (int i = state.activeConnections.size(); i > 0; i--) {
try {
//从PoolState.activeConnections集合中获取PooledConnection 对象
PooledConnection conn = state.activeConnections.remove(i - 1);
//将PooledConnection对象设置为无效
conn.invalidate();
//获取真正的数据库连接对象
Connection realConn = conn.getRealConnection();
// 回滚未提交的事务
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
// 关闭真正的数据库连接
realConn.close();
} catch (Exception e) {
// ignore
}
}
for (int i = state.idleConnections.size(); i > 0; i--) {
try {
PooledConnection conn = state.idleConnections.remove(i - 1);
conn.invalidate();
Connection realConn = conn.getRealConnection();
if (!realConn.getAutoCommit()) {
realConn.rollback();
}
realConn.close();
} catch (Exception e) {
// ignore
}
}
}
if (log.isDebugEnabled()) {
log.debug("PooledDataSource forcefully closed/removed all connections.");
}
}
}
public interface Transaction {
/**
* Retrieve inner database connection.
* @return DataBase connection
* @throws SQLException
* the SQL exception
*/
// 获取对应的数据库连接对象
Connection getConnection() throws SQLException;
/**
* Commit inner database connection.
* @throws SQLException
* the SQL exception
*/
// 提交事务
void commit() throws SQLException;
/**
* Rollback inner database connection.
* @throws SQLException
* the SQL exception
*/
// 回滚事务
void rollback() throws SQLException;
/**
* Close inner database connection.
* @throws SQLException
* the SQL exception
*/
//关闭数据库连接
void close() throws SQLException;
/**
* Get transaction timeout if set.
*
* @return the timeout
* @throws SQLException
* the SQL exception
*/
//获取事务超时时间
Integer getTimeout() throws SQLException;
}
public class JdbcTransaction implements Transaction {
private static final Log log = LogFactory.getLog(JdbcTransaction.class);
//事务对应的数据库连接
protected Connection connection;
// 数据库连接所属的DataSource
protected DataSource dataSource;
// 事务隔离级别
protected TransactionIsolationLevel level;
// 是否自动提交
protected boolean autoCommit;
}
public interface TransactionFactory {
/**
* Sets transaction factory custom properties.
* @param props
* the new properties
*/
// 完成对TransactionFactory的自定义配置
default void setProperties(Properties props) {
// NOP
}
/**
* Creates a {@link Transaction} out of an existing connection.
* @param conn Existing database connection
* @return Transaction
* @since 3.1.0
*/
//在指定的连接上创建Transaction 对象
Transaction newTransaction(Connection conn);
/**
* Creates a {@link Transaction} out of a datasource.
* @param dataSource DataSource to take the connection from
* @param level Desired isolation level
* @param autoCommit Desired autocommit
* @return Transaction
* @since 3.1.0
*/
//从指定数据源中获取数据库连接,并在此连接之上创建Transaction 对象
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
}
/**
* @author Clinton Begin
* @author Eduardo Macarron
* @author Lasse Voss
* 是Mapper 接口及其对应的代理对象工厂的注册中心。
*/
public class MapperRegistry {
//Configuration 对象,MyBatis 全局唯一的配置对象,其中包含了所有配置信息
private final Configuration config;
//记录了Mapper 接口与对应MapperProxyFactory 之间的关系
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
public MapperRegistry(Configuration config) {
this.config = config;
}
@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//查找指定type 对应的MapperProxyFactory 对象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//创建实现了type 接口的代理对象
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
public <T> boolean hasMapper(Class<T> type) {
return knownMappers.containsKey(type);
}
public <T> void addMapper(Class<T> type) {
//检测type 是否为接口
if (type.isInterface()) {
//检测是否已经加载过该接口
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
//将Mapper 接口对应的Class 对象和MapperProxyFactory 对象添加到knownMappers 集合
knownMappers.put(type, new MapperProxyFactory<>(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.
//XML 解析和注解的处理
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
} }
public class MapperProxyFactory<T> {
//当前MapperProxyFactory 对象可以创建实现了mapper Interface 接口的代理对象,
private final Class<T> mapperInterface;
//缓存, key 是mapperinterface接口中某方法对应的Method 对象, value 是对应的MapperMethod对象
private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public Class<T> getMapperInterface() {
return mapperInterface;
}
public Map<Method, MapperMethodInvoker> getMethodCache() {
return methodCache;
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
//创建实现了mapperinterface 接口的代理对象
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
//创建MapperProxy 对象,每次调用都会创建新的MapperProxy 对象
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
public class MapperProxy<T> implements InvocationHandler, Serializable {
private static final long serialVersionUID = -4724728412955527868L;
private static final int ALLOWED_MODES = MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED
| MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC;
private static final Constructor<Lookup> lookupConstructor;
private static final Method privateLookupInMethod;
//记录了关联的SqlSession 对象
private final SqlSession sqlSession;
//Mapper 接口对应的Class 对象
private final Class<T> mapperInterface;
// 用于缓存MapperMethod 对象,其中key 是Mapper 接口中方法对应的Method 对象, value 是对应的
// MapperMethod 对象。MapperMethod 对象会完成参数转换以及SQL 语句的执行功能
// 需要注意的是, MapperMethod 中并不记录任何状态相关的信息,所以可以在多个代理对象之间共享
private final Map<Method, MapperMethodInvoker> methodCache;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//如果目标方法继承自Object ,则直接调用目标方法
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
//从缓存中获取MapperMethod 对象,如缓存中没有,则创建新的MapperMethod 对象并添加到缓存中
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
}
/**
* @author Clinton Begin
* @author Eduardo Macarron
* @author Lasse Voss
* @author Kazuki Shimizu
* 封装了Mapper 接口中对应方法的信息,以及对应SQL 语句的信息
*/
public class MapperMethod {
// 记录了SQL 语句的名称和类型
private final SqlCommand command;
// Mapper 接口中对应方法的相关信息
private final MethodSignature method;
public static class SqlCommand {
//记录SQL 语句的名称
private final String name;
//记录SQL 语句的类型
private final SqlCommandType type;
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
final String methodName = method.getName();
final Class<?> declaringClass = method.getDeclaringClass();
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
configuration);
if (ms == null) {
//处理@ Flush i主解
if (method.getAnnotation(Flush.class) != null) {
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): "
+ mapperInterface.getName() + "." + methodName);
}
} else {
//初始化name 和type
name = ms.getId();
type = ms.getSqlCommandType();
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
Class<?> declaringClass, Configuration configuration) {
// SQL 语句的名称是由Mapper 接口的名称与对应的方法名称组成的
String statementId = mapperInterface.getName() + "." + methodName;
//检测是否有该名称的SQL 语句
if (configuration.hasStatement(statementId)) {
//从Configuration.mappedStatements集合中查找对应的MappedStatement对象
return configuration.getMappedStatement(statementId);
} else if (mapperInterface.equals(declaringClass)) {
return null;
}
//如果指定方法是在父接口中定义的, 则在此进行继承结构的处理
for (Class<?> superInterface : mapperInterface.getInterfaces()) {
if (declaringClass.isAssignableFrom(superInterface)) {
MappedStatement ms = resolveMappedStatement(superInterface, methodName,
declaringClass, configuration);
if (ms != null) {
return ms;
}
}
}
return null;
}
}
public static class MethodSignature {
//返回值类型是否为Collection 类型或是数组类型
private final boolean returnsMany;
//返回值类型是否为Map类型
private final boolean returnsMap;
//返回值类型是否为Void
private final boolean returnsVoid;
// 返回值是否为Cursor 类型
private final boolean returnsCursor;
private final boolean returnsOptional;
// 返回值类型
private final Class<?> returnType;
//如果返回值类型是Map ,则该字段记录了作为key 的列名
private final String mapKey;
//用来标记该方法参数列表中ResultHandler 类型参数的位置
private final Integer resultHandlerIndex;
//用来标记该方法参数列表中RowBounds 类型参数的位置
private final Integer rowBoundsIndex;
//该方法对应的ParamNameResolver 对象
private final ParamNameResolver paramNameResolver;
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
//解析方法的返回值类型
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
//初始化returnsVoid 、returnsMany 、returnsCursor 、map Key 、returnsMap 等字段
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
//若MethodSignature 对应方法的返回位是Map 且指定了@ Map Key注解,则使用getMapKey ()方法处理
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
//初始化rowBoundsindex 和resultHandlerindex 字段
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
//创建ParamNameResolver 对象
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
//查找指定类型的参数在参数列表中的位置
private Integer getUniqueParamIndex(Method method, Class<?> paramType) {
Integer index = null;
final Class<?>[] argTypes = method.getParameterTypes();
for (int i = 0; i < argTypes.length; i++) {
if (paramType.isAssignableFrom(argTypes[i])) {
//记录paramType 类型参数在参数列表中的位置索引
if (index == null) {
index = i;
} else {
// RowBounds 和ResultHandler 类型的参数只能有一个,不能重复出现
throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters");
}
}
}
return index;
}
//负责将args []数纽( 用户传入的实参列表)转换成SQL 语句对应的参数列表,
public Object convertArgsToSqlCommandParam(Object[] args) {
return paramNameResolver.getNamedParams(args);
}
}
//根据SQL 语句的类型调用SqI Session 对应的方法完成数据库操作。
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//根据SQL 语句的类型调用SqlSession 对应的方法
switch (command.getType()) {
case INSERT: {
//使用ParamNameResolver处理args []数组(用户传入的实参列表),将用户传入的实参与指定参数名称关联起来
Object param = method.convertArgsToSqlCommandParam(args);
//调用SqlSession.insert ()方法, rowCountResult ()方法会根据method 字段中记录的方法的 返回值类型对结果进行转换
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
//处理返回值为void 且ResultSet 通过ResultHandler 处理的方法
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
//处理返回值为集合或数组的方法
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
//处理返回值为Map 的方法
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
// 处理返回值为Curs or 的方法
result = executeForCursor(sqlSession, args);
} else {
//处理返回值为单一对象的方法
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
private Object rowCountResult(int rowCount) {
final Object result;
if (method.returnsVoid()) {
//Mapper 接口中相应方法的返回值为void
result = null;
} else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
// Mapper 接口中相应方法的返回值为int 或Integer
result = rowCount;
} else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
// Mapper 接口中相应方法的返回值为long 或Long
result = (long) rowCount;
} else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
// Mapper 接口中相应方法的返回值为boolean 或Boolean
result = rowCount > 0;
} else {
throw new BindingException("Mapper method '" + command.getName() + "' has an unsupported return type: " + method.getReturnType());
}
return result;
}
//使用ResultHandler处理查询结果集
private void executeWithResultHandler(SqlSession sqlSession, Object[] args) {
//获取SQL 语句对应的MappedStatement 对象, MappedStatement 中记录了SQL 语句相关信息,
MappedStatement ms = sqlSession.getConfiguration().getMappedStatement(command.getName());
//当使用ResultHandler 处理结采集时,必须指定ResultMap 或ResultType
if (!StatementType.CALLABLE.equals(ms.getStatementType())
&& void.class.equals(ms.getResultMaps().get(0).getType())) {
throw new BindingException("method " + command.getName()
+ " needs either a @ResultMap annotation, a @ResultType annotation,"
+ " or a resultType attribute in XML so a ResultHandler can be used as a parameter.");
}
Object param = method.convertArgsToSqlCommandParam(args);
//检测参数列表中是否有RowBounds 类型的参数
if (method.hasRowBounds()) {
//获取RowBounds对象,根据MethodSignature.rowBoundsindex 字段指定位置,从args 数组中 查找。获取ResultHandler 对象的原理相同
RowBounds rowBounds = method.extractRowBounds(args);
//调用SqlSession.select ()方法,执行查询,并由指定的ResultHandler 处理结果对象
sqlSession.select(command.getName(), param, rowBounds, method.extractResultHandler(args));
} else {
sqlSession.select(command.getName(), param, method.extractResultHandler(args));
}
}
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
List<E> result;
//参数列表转换
Object param = method.convertArgsToSqlCommandParam(args);
//检测是否指定了RowBounds 参数
if (method.hasRowBounds()) {
RowBounds rowBounds = method.extractRowBounds(args);
//调用SqlSession.selectList ()方法完成查询
result = sqlSession.selectList(command.getName(), param, rowBounds);
} else {
result = sqlSession.selectList(command.getName(), param);
}
// issue #510 Collections & arrays support
//将结果集转换为数组或Collection 集合
if (!method.getReturnType().isAssignableFrom(result.getClass())) {
if (method.getReturnType().isArray()) {
return convertToArray(result);
} else {
return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
}
}
return result;
}
private <E> Object convertToDeclaredCollection(Configuration config, List<E> list) {
//使用ObjectFactory ,通过反射方式创建集合对象
Object collection = config.getObjectFactory().create(method.getReturnType());
//创建MetaObject 对象
MetaObject metaObject = config.newMetaObject(collection);
//实际上就是调用Collection. addAll ()方法
metaObject.addAll(list);
return collection;
}
@SuppressWarnings("unchecked")
private <E> Object convertToArray(List<E> list) {
//获取数纽元素的类型
Class<?> arrayComponentType = method.getReturnType().getComponentType();
//创建数组对象
Object array = Array.newInstance(arrayComponentType, list.size());
//将list 中每一项都添加到数组中
if (arrayComponentType.isPrimitive()) {
for (int i = 0; i < list.size(); i++) {
Array.set(array, i, list.get(i));
}
return array;
} else {
return list.toArray((E[]) array);
}
}
}
public class ParamNameResolver {
//记录参数在参数列表中的位置索引与参数名称之间的对应关系
private final SortedMap<Integer, String> names;
//记录对应方法的参数列表中是否使用了@Param 注解。
private boolean hasParamAnnotation;
public ParamNameResolver(Configuration config, Method method) {
this.useActualParamName = config.isUseActualParamName();
//获取参数列表中每个参数的类型
final Class<?>[] paramTypes = method.getParameterTypes();
//获取参数列表上的注解
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
//该集合用于记录参数索引与参数名称的对应关系
final SortedMap<Integer, String> map = new TreeMap<>();
int paramCount = paramAnnotations.length;
// get names from @Param annotations
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
//如参数是RowBounds 类型或ResultHandler 类型,跳过对该参数的分析
if (isSpecialParameter(paramTypes[paramIndex])) {
// skip special parameters
continue;
}
String name = null;
// 遥历该参数对应的i主解集合
for (Annotation annotation : paramAnnotations[paramIndex]) {
// @Param出现过一次,就将hasParamAnnotation 初始化为true
if (annotation instanceof Param) {
hasParamAnnotation = true;
//获取自Param注解指定的参数名称
name = ((Param) annotation).value();
break;
}
}
if (name == null) {
// @Param was not specified.
//该参数没有对应的@Param注解,则根据配置决定是否使用参数实际名称作为其名称
if (useActualParamName) {
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
//使用参数的索引作为其名称
name = String.valueOf(map.size());
}
}
// 记录到map 中保存
map.put(paramIndex, name);
}
// 初始化names 集合
names = Collections.unmodifiableSortedMap(map);
}
private String getActualParamName(Method method, int paramIndex) {
return ParamNameUtil.getParamNames(method).get(paramIndex);
}
//isSpecialParameter ()方法用来过滤RowBounds 和ResultHandler 两种类型的参数
private static boolean isSpecialParameter(Class<?> clazz) {
return RowBounds.class.isAssignableFrom(clazz) || ResultHandler.class.isAssignableFrom(clazz);
}
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
// 无参数,返回null
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
// 未使用@Param且只有一个参数
Object value = args[names.firstKey()];
return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null);
} else {
//处理使用@Paramd主解指定了参数名称或有多个参数的情况
// param这个Map中记录了参数名称与实参之间的对应关系。ParamMap继承了HashMap ,如果向
// ParamMap 中添加已经存在的key ,会报错,其他行为与HashMap 相同
final Map<String, Object> param = new ParamMap<>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
//将参数名与实参对应关系记录到pa ram 中
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
// 下面是为参数创建” param+索引”格式的默认参数名称,例如: paraml , param2等,并添加到param 集合中
final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
// ensure not to overwrite parameter named with @Param
//如@Param主解指定的参数名称就是” param+索引”格式的,则不需要再添加
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
}
public interface Cache {
/**
* @return The identifier of this cache
*/
// 该缓存对象的id
String getId();
/**
* @param key
* Can be any object but usually it is a {@link CacheKey}
* @param value
* The result of a select.
*/
// 向缓存中添加数据,一般情况下, key 是Ca cheKey , value 是查询结果
void putObject(Object key, Object value);
/**
* @param key
* The key
* @return The object stored in the cache.
*/
// 根据指定的key ,在缓存中查找对应的结果对象
Object getObject(Object key);
/**
* As of 3.3.0 this method is only called during a rollback
* for any previous value that was missing in the cache.
* This lets any blocking cache to release the lock that
* may have previously put on the key.
* A blocking cache puts a lock when a value is null
* and releases it when the value is back again.
* This way other threads will wait for the value to be
* available instead of hitting the database.
*
*
* @param key
* The key
* @return Not used
*/
Object removeObject(Object key);
/**
* Clears this cache instance.
*/
void clear();
/**
* Optional. This method is not called by the core.
*
* @return The number of elements stored in the cache (not its capacity).
*/
//缓存项的个数,该方法不会被MyBatis 核心代码使用
int getSize();
/**
* Optional. As of 3.2.6 this method is no longer called by the core.
*
* Any locking needed by the cache must be provided internally by the cache provider.
*
* @return A ReadWriteLock
*/
//获取读写锁,该方法不会被MyBatis 核心代码使用,所以可提供空实现
default ReadWriteLock getReadWriteLock() {
return null;
}
}
public class PerpetualCache implements Cache {
//Cache 对象的唯一标识
private final String id;
//用于记录缓存项的Map 对象
private final Map<Object, Object> cache = new HashMap<>();
}
/**
* Simple blocking decorator
*
* Simple and inefficient version of EhCache's BlockingCache decorator.
* It sets a lock over a cache key when the element is not found in cache.
* This way, other threads will wait until this element is filled instead of hitting the database.
*
* @author Eduardo Macarron
*
* 阻塞版本的缓存装饰器,它会保证只有一个线程到数据库中查找指定key对应的数据
*/
public class BlockingCache implements Cache {
// 阻塞超时时长
private long timeout;
// 被装饰的底层Cache 对象
private final Cache delegate;
//每个key 都有对应的ReentrantLock 对象
private final ConcurrentHashMap<Object, ReentrantLock> locks;
@Override
public void putObject(Object key, Object value) {
try {
// 向缓存中添加缓存项
delegate.putObject(key, value);
} finally {
//释放锁
releaseLock(key);
}
}
@Override
public Object getObject(Object key) {
//获取该key 对应的锁
acquireLock(key);
//查询key
Object value = delegate.getObject(key);
//缓存有key 对应的缓存项,择放锁,否则继续持有锁
if (value != null) {
releaseLock(key);
}
return value;
}
private void acquireLock(Object key) {
//获取ReentrantLock 对象
Lock lock = getLockForKey(key);
//获取锁,带超时时长
if (timeout > 0) {
try {
boolean acquired = lock.tryLock(timeout, TimeUnit.MILLISECONDS);
//超时,则抛出异常
if (!acquired) {
throw new CacheException("Couldn't get a lock in " + timeout + " for the key " + key + " at the cache " + delegate.getId());
}
} catch (InterruptedException e) {
throw new CacheException("Got interrupted while trying to acquire lock for key " + key, e);
}
} else {
//获取锁,不带起时时长
lock.lock();
}
}
private void releaseLock(Object key) {
ReentrantLock lock = locks.get(key);
//锁是否被当前线程持有
if (lock.isHeldByCurrentThread()) {
//释放锁
lock.unlock();
}
}
}
/**
* FIFO (first in, first out) cache decorator.
*先入先出版本的装饰器, 当向缓存添加数据时,如果缓存项的个数已经达到上限, 则会将缓存中
* 最老( 即最早进入缓存) 的缓存项删除。
* @author Clinton Begin
*/
public class FifoCache implements Cache {
//底层被装饰的底层Cache 对象
private final Cache delegate;
// 用于记录key 进入缓存的先后顺序, 使用的是LinkedList
/**
* Lru (least recently used) cache decorator.
*按照近期最少使用算法( Least Recently Used, LRU )进行缓存清理的装饰器,
* 在需要清理缓存时它会清除最近最少使用的缓存工页
* @author Clinton Begin
*/
public class LruCache implements Cache {
// 被装饰的底层Cache 对象
private final Cache delegate;
// LinkedHashMap
/**
* Soft Reference cache decorator
* Thanks to Dr. Heinz Kabutz for his guidance here.
*
* @author Clinton Begin
*/
public class SoftCache implements Cache {
//在SoftCache中,最近使用的一部分缓存项不会被GC 回收,这就是通过将其value
// 添加到hardLinksToAvoidGarbageCollection集合中实现的(即有强引用指向其value)
// hardLinksToAvoidGarbageCollection集合是LinkedList
/**
* 周期性清理缓存的装饰器
* @author Clinton Begin
*/
public class ScheduledCache implements Cache {
private final Cache delegate;
//记录两次缓存清理之间的时间间隔,默认是一小时
protected long clearInterval;
// 记录最近一次清理的时间戳
protected long lastClear;
}
ublic class CacheKey implements Cloneable, Serializable {
private static final long serialVersionUID = 1146682552656046210L;
public static final CacheKey NULL_CACHE_KEY = new CacheKey() {
@Override
public void update(Object object) {
throw new CacheException("Not allowed to update a null cache key instance.");
}
@Override
public void updateAll(Object[] objects) {
throw new CacheException("Not allowed to update a null cache key instance.");
}
};
private static final int DEFAULT_MULTIPLIER = 37;
private static final int DEFAULT_HASHCODE = 17;
//参与计算hashcode ,默认位是37
private final int multiplier;
// CacheKey 对象的hashcode ,初始位是17
private int hashcode;
//校验和
private long checksum;
// updateList 集合的个数
private int count;
// 8/21/2017 - Sonarlint flags this as needing to be marked transient. While true if content is not serializable, this
// is not always true and thus should not be marked transient.
//由该集合中的所有对象共同决定两个CacheKey 是否相同
/*
updateList集合值
MappedStatement的id 。
指定查询结果集的范围,也就是RowBounds .offset 和RowBounds.limit 。
查询所使用的SQL 语句,也就是boundSql.getSql ()方法返回的SQL 语句,其中可能包含“?”占位符。
用户传递给上述SQL 语句的实际参数值。
*/
private List<Object> updateList;
@Override
public boolean equals(Object object) {
//是否走向一对象
if (this == object) {
return true;
}
// 是否类型相同
if (!(object instanceof CacheKey)) {
return false;
}
final CacheKey cacheKey = (CacheKey) object;
// 比较hashcode
if (hashcode != cacheKey.hashcode) {
return false;
}
//比较checksum
if (checksum != cacheKey.checksum) {
return false;
}
// 比较count
if (count != cacheKey.count) {
return false;
}
// 比较updateList 中每一项
for (int i = 0; i < updateList.size(); i++) {
Object thisObject = updateList.get(i);
Object thatObject = cacheKey.updateList.get(i);
if (!ArrayUtil.equals(thisObject, thatObject)) {
return false;
}
}
return true;
}
}