StaticTextSqlNode 静态文本的SqlNode实现类
public class StaticTextSqlNode implements SqlNode {
//静态文本
private final String text;
public StaticTextSqlNode(String text) {
this.text = text;
}
@Override
//直接拼接到context中
public boolean apply(DynamicContext context) {
context.appendSql(text);
return true;
}
}
TextSqlNode 跟static区别是不确定是否是静态文本。
public class TextSqlNode implements SqlNode {
//文本
private final String text;
private final Pattern injectionFilter;
public TextSqlNode(String text) {
this(text, null);
}
public TextSqlNode(String text, Pattern injectionFilter) {
this.text = text;
this.injectionFilter = injectionFilter;
}
//判断是否是动态文本,只要存在${XXX}就是动态文本
public boolean isDynamic() {
//创建 DynamicCheckerTokenParser 对象
DynamicCheckerTokenParser checker = new DynamicCheckerTokenParser();
//创建 GenericTokenParser 对象
GenericTokenParser parser = createParser(checker);
//执行解析
parser.parse(text);
//判断是否是动态文本
return checker.isDynamic();
}
@Override
public boolean apply(DynamicContext context) {
//创建BindingTokenParser对象,创建GenericTokenParser对象
GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter));
//执行解析,将解析结果添加到context中
context.appendSql(parser.parse(text));
return true;
}
//只要存在${}就是动态文本
private GenericTokenParser createParser(TokenHandler handler) {
return new GenericTokenParser("${", "}", handler);
}
private static class BindingTokenParser implements TokenHandler {
private DynamicContext context;
private Pattern injectionFilter;
public BindingTokenParser(DynamicContext context, Pattern injectionFilter) {
this.context = context;
this.injectionFilter = injectionFilter;
}
@Override
public String handleToken(String content) {
//初始化value属性到context中
Object parameter = context.getBindings().get("_parameter");
if (parameter == null) {
context.getBindings().put("value", null);
} else if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
context.getBindings().put("value", parameter);
}
//使用OGNL表达式获得对应的值
Object value = OgnlCache.getValue(content, context.getBindings());
String srtValue = (value == null ? "" : String.valueOf(value)); // issue #274 return "" instead of "null"
checkInjection(srtValue);
//返回该值
return srtValue;
}
private void checkInjection(String value) {
if (injectionFilter != null && !injectionFilter.matcher(value).matches()) {
throw new ScriptingException("Invalid input. Please conform to regex" + injectionFilter.pattern());
}
}
}
//内部类
private static class DynamicCheckerTokenParser implements TokenHandler {
//是否是动态文本
private boolean isDynamic;
public DynamicCheckerTokenParser() {
// Prevent Synthetic Access
}
public boolean isDynamic() {
return isDynamic;
}
@Override
//当检查到token,标记为动态文本
public String handleToken(String content) {
this.isDynamic = true;
return null;
}
}
}
MixedSqlNode
public class MixedSqlNode implements SqlNode {
private final List<SqlNode> contents;
public MixedSqlNode(List<SqlNode> contents) {
this.contents = contents;
}
@Override
//遍历SqlNode数组,逐个调用
public boolean apply(DynamicContext context) {
for (SqlNode sqlNode : contents) {
sqlNode.apply(context);
}
return true;
}
}
OgnlCache Ognl的缓存类
public final class OgnlCache {
//单例
private static final OgnlMemberAccess MEMBER_ACCESS = new OgnlMemberAccess();
private static final OgnlClassResolver CLASS_RESOLVER = new OgnlClassResolver();
//表达式的缓存的映射,key是表达式,value是表达式的缓存
private static final Map<String, Object> expressionCache = new ConcurrentHashMap<>();
private OgnlCache() {
// Prevent Instantiation of Static Class
}
public static Object getValue(String expression, Object root) {
try {
//创建OGNL Context对象
Map context = Ognl.createDefaultContext(root, MEMBER_ACCESS, CLASS_RESOLVER, null);
//解析表达式,获得表达式对应的值
return Ognl.getValue(parseExpression(expression), context, root);
} catch (OgnlException e) {
throw new BuilderException("Error evaluating expression '" + expression + "'. Cause: " + e, e);
}
}
//解析表达式
private static Object parseExpression(String expression) throws OgnlException {
Object node = expressionCache.get(expression);
if (node == null) {
node = Ognl.parseExpression(expression);
expressionCache.put(expression, node);
}
return node;
}
}
OgnlMemberAccess 实现了MemberAccess接口,OGNL成员访问器实现类
class OgnlMemberAccess implements MemberAccess {
//是否可以修改成员的可访问
private final boolean canControlMemberAccessible;
OgnlMemberAccess() {
this.canControlMemberAccessible = Reflector.canControlMemberAccessible();
}
@Override
public Object setup(Map context, Object target, Member member, String propertyName) {
Object result = null;
//判断是否可以修改
if (isAccessible(context, target, member, propertyName)) {
AccessibleObject accessible = (AccessibleObject) member;
//不可访问就设置为可以访问
if (!accessible.isAccessible()) {
result = Boolean.FALSE;
accessible.setAccessible(true);
}
}
return result;
}
@Override
public void restore(Map context, Object target, Member member, String propertyName,
Object state) {
if (state != null) {
//修改为原来的可访问
((AccessibleObject) member).setAccessible(((Boolean) state));
}
}
@Override
public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
return canControlMemberAccessible;
}
}
OgnlClassResolver OGNL 类解析器实现类
public class OgnlClassResolver extends DefaultClassResolver {
@Override
protected Class toClassForName(String className) throws ClassNotFoundException {
return Resources.classForName(className);
}
}
ExpressionEvaluator OGNL 表达式计算器
public class ExpressionEvaluator {
//判断表达式对应的值,是否为true
public boolean evaluateBoolean(String expression, Object parameterObject) {
//获得表达式对应的值
Object value = OgnlCache.getValue(expression, parameterObject);
//如果是Boolean类型,直接判断
if (value instanceof Boolean) {
return (Boolean) value;
}
//如果是 Number 类型,则判断不等于 0
if (value instanceof Number) {
return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0;
}
return value != null;
}
//获得表达式对应的集合
public Iterable<?> evaluateIterable(String expression, Object parameterObject) {
// 获得表达式对应的值
Object value = OgnlCache.getValue(expression, parameterObject);
if (value == null) {
throw new BuilderException("The expression '" + expression + "' evaluated to a null value.");
}
// 如果是 Iterable 类型,直接返回
if (value instanceof Iterable) {
return (Iterable<?>) value;
}
// 如果是数组类型,则返回数组
if (value.getClass().isArray()) {
int size = Array.getLength(value);
List<Object> answer = new ArrayList<>();
for (int i = 0; i < size; i++) {
Object o = Array.get(value, i);
answer.add(o);
}
return answer;
}
// 如果是 Map 类型,则返回 Map.entrySet 集合
if (value instanceof Map) {
return ((Map) value).entrySet();
}
throw new BuilderException("Error evaluating expression '" + expression + "'. Return value (" + value + ") was not iterable.");
}
}
接下来进入SqlSource,代表着从Mapper.xml或方法注解上读取的一条SQL内容
public interface SqlSource {
//根据传入的参数对象返回BoundSql对象
BoundSql getBoundSql(Object parameterObject);
}
SqlSourceBuilder 负责将SQL语句中的#{XX}替换成对应的?占位符,并且获取?占位符号对应的ParamterMapping对象
public class SqlSourceBuilder extends BaseBuilder {
private static final String parameterProperties = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
//构造函数
public SqlSourceBuilder(Configuration configuration) {
super(configuration);
}
//解析原始SQL,成为SqlSource对象
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
//创建ParameterMappingTokenHandler对象
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
//创建 GenericTokenParser 对象
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
//执行解析
String sql = parser.parse(originalSql);
//创建 StaticSqlSource 对象
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}
//内部类。负责将#{}替换成?占位符
private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
//ParamterMapping数组
private List<ParameterMapping> parameterMappings = new ArrayList<>();
//参数类型
private Class<?> parameterType;
//附加参数对应的MetaObject对象
private MetaObject metaParameters;
//构造函数
public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
super(configuration);
this.parameterType = parameterType;
this.metaParameters = configuration.newMetaObject(additionalParameters);
}
public List<ParameterMapping> getParameterMappings() {
return parameterMappings;
}
@Override
public String handleToken(String content) {
//构建 ParameterMapping 对象,并添加到 parameterMappings 中
parameterMappings.add(buildParameterMapping(content));
//返回?占位符
return "?";
}
//构建ParameterMapping对象
private ParameterMapping buildParameterMapping(String content) {
//解析成Map集合
Map<String, String> propertiesMap = parseParameterMapping(content);
//获得属性的名称和类型
String property = propertiesMap.get("property");
Class<?> propertyType;
if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
propertyType = metaParameters.getGetterType(property);
} else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
propertyType = parameterType;
} else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
propertyType = java.sql.ResultSet.class;
} else if (property == null || Map.class.isAssignableFrom(parameterType)) {
propertyType = Object.class;
} else {
MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
if (metaClass.hasGetter(property)) {
propertyType = metaClass.getGetterType(property);
} else {
propertyType = Object.class;
}
}
//创建 ParameterMapping.Builder 对象
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
Class<?> javaType = propertyType;
String typeHandlerAlias = null;
for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
String name = entry.getKey();
String value = entry.getValue();
if ("javaType".equals(name)) {
javaType = resolveClass(value);
builder.javaType(javaType);
} else if ("jdbcType".equals(name)) {
builder.jdbcType(resolveJdbcType(value));
} else if ("mode".equals(name)) {
builder.mode(resolveParameterMode(value));
} else if ("numericScale".equals(name)) {
builder.numericScale(Integer.valueOf(value));
} else if ("resultMap".equals(name)) {
builder.resultMapId(value);
} else if ("typeHandler".equals(name)) {
typeHandlerAlias = value;
} else if ("jdbcTypeName".equals(name)) {
builder.jdbcTypeName(value);
} else if ("property".equals(name)) {
// Do Nothing
} else if ("expression".equals(name)) {
throw new BuilderException("Expression based parameters are not supported yet");
} else {
throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content + "}. Valid properties are " + parameterProperties);
}
}
//如果typeHandlerAlias非空,就获得对应的TypeHandler对象。
if (typeHandlerAlias != null) {
builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
}
//创建 ParameterMapping 对象
return builder.build();
}
//解析成Map集合
private Map<String, String> parseParameterMapping(String content) {
try {
return new ParameterExpression(content);
} catch (BuilderException ex) {
throw ex;
} catch (Exception ex) {
throw new BuilderException("Parsing error was found in mapping #{" + content + "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
}
}
}
}
SqlSource的实现类
StaticSqlSource
public class StaticSqlSource implements SqlSource {
//静态sql
private final String sql;
//ParameterMapping 集合
private final List<ParameterMapping> parameterMappings;
private final Configuration configuration;
public StaticSqlSource(Configuration configuration, String sql) {
this(configuration, sql, null);
}
public StaticSqlSource(Configuration configuration, String sql, List<ParameterMapping> parameterMappings) {
this.sql = sql;
this.parameterMappings = parameterMappings;
this.configuration = configuration;
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
//创建BoundSql对象
return new BoundSql(configuration, sql, parameterMappings, parameterObject);
}
}
DynamicSqlSource
public class DynamicSqlSource implements SqlSource {
private final Configuration configuration;
//根SqlNode对象
private final SqlNode rootSqlNode;
public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
this.configuration = configuration;
this.rootSqlNode = rootSqlNode;
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
//应用rootSqlNode
DynamicContext context = new DynamicContext(configuration, parameterObject);
rootSqlNode.apply(context);
//构建SqlSourceBuilder对象
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
//解析出SqlSource对象
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
//添加附加参数到 BoundSql 对象中
for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return boundSql;
}
}
RawSqlSource
public class RawSqlSource implements SqlSource {
private final SqlSource sqlSource;
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}
public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
//创建SqlSourceBuilder对象
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
//获得SqlSource对象
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
}
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
//创建DynamicContext对象
DynamicContext context = new DynamicContext(configuration, null);
// 解析出 SqlSource 对象
rootSqlNode.apply(context);
// 获得 sql
return context.getSql();
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
return sqlSource.getBoundSql(parameterObject);
}
}
ProviderSqlSource 基于方法上的@ProviderXXX注解的SqlSource实现类
public class ProviderSqlSource implements SqlSource {
private final Configuration configuration;
private final SqlSourceBuilder sqlSourceParser;
//注解对应的类
private final Class<?> providerType;
//注解对应的方法
private Method providerMethod;
//注解的对应的方法的参数名数组
private String[] providerMethodArgumentNames;
//注解的对应的方法的参数类型数组
private Class<?>[] providerMethodParameterTypes;
//如果有ProviderContext类型就创建ProviderContext对象
private ProviderContext providerContext;
//ProviderContext 类型的参数,在数组中的位置
private Integer providerContextIndex;
/**
* @deprecated Please use the {@link #ProviderSqlSource(Configuration, Object, Class, Method)} instead of this.
*/
@Deprecated
public ProviderSqlSource(Configuration configuration, Object provider) {
this(configuration, provider, null, null);
}
/**
* @since 3.4.5
*/
public ProviderSqlSource(Configuration configuration, Object provider, Class<?> mapperType, Method mapperMethod) {
String providerMethodName;
try {
this.configuration = configuration;
//创建SqlSourceBuilder对象
this.sqlSourceParser = new SqlSourceBuilder(configuration);
//获得 @ProviderXXX 注解的对应的类
this.providerType = (Class<?>) provider.getClass().getMethod("type").invoke(provider);
//获得 @ProviderXXX 注解的对应的方法相关的信息
providerMethodName = (String) provider.getClass().getMethod("method").invoke(provider);
for (Method m : this.providerType.getMethods()) {
if (providerMethodName.equals(m.getName()) && CharSequence.class.isAssignableFrom(m.getReturnType())) {
if (providerMethod != null){
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
+ providerMethodName + "' is found multiple in SqlProvider '" + this.providerType.getName()
+ "'. Sql provider method can not overload.");
}
this.providerMethod = m;
this.providerMethodArgumentNames = new ParamNameResolver(configuration, m).getNames();
this.providerMethodParameterTypes = m.getParameterTypes();
}
}
} catch (BuilderException e) {
throw e;
} catch (Exception e) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Cause: " + e, e);
}
if (this.providerMethod == null) {
throw new BuilderException("Error creating SqlSource for SqlProvider. Method '"
+ providerMethodName + "' not found in SqlProvider '" + this.providerType.getName() + "'.");
}
//初始化 providerContext 和 providerContextIndex 属性
for (int i = 0; i< this.providerMethodParameterTypes.length; i++) {
Class<?> parameterType = this.providerMethodParameterTypes[i];
if (parameterType == ProviderContext.class) {
if (this.providerContext != null){
throw new BuilderException("Error creating SqlSource for SqlProvider. ProviderContext found multiple in SqlProvider method ("
+ this.providerType.getName() + "." + providerMethod.getName()
+ "). ProviderContext can not define multiple in SqlProvider method argument.");
}
this.providerContext = new ProviderContext(mapperType, mapperMethod);
this.providerContextIndex = i;
}
}
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
//创建SqlSource对象
SqlSource sqlSource = createSqlSource(parameterObject);
//获得 BoundSql 对象
return sqlSource.getBoundSql(parameterObject);
}
private SqlSource createSqlSource(Object parameterObject) {
try {
//获得SQL
int bindParameterCount = providerMethodParameterTypes.length - (providerContext == null ? 0 : 1);
String sql;
if (providerMethodParameterTypes.length == 0) {
sql = invokeProviderMethod();
} else if (bindParameterCount == 0) {
sql = invokeProviderMethod(providerContext);
} else if (bindParameterCount == 1 &&
(parameterObject == null || providerMethodParameterTypes[(providerContextIndex == null || providerContextIndex == 1) ? 0 : 1].isAssignableFrom(parameterObject.getClass()))) {
sql = invokeProviderMethod(extractProviderMethodArguments(parameterObject));
} else if (parameterObject instanceof Map) {
@SuppressWarnings("unchecked")
Map<String, Object> params = (Map<String, Object>) parameterObject;
sql = invokeProviderMethod(extractProviderMethodArguments(params, providerMethodArgumentNames));
} else {
throw new BuilderException("Error invoking SqlProvider method ("
+ providerType.getName() + "." + providerMethod.getName()
+ "). Cannot invoke a method that holds "
+ (bindParameterCount == 1 ? "named argument(@Param)": "multiple arguments")
+ " using a specifying parameterObject. In this case, please specify a 'java.util.Map' object.");
}
//获得参数
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
//替换掉Sql上的属性,解析出SqlSource对象
return sqlSourceParser.parse(replacePlaceholder(sql), parameterType, new HashMap<String, Object>());
} catch (BuilderException e) {
throw e;
} catch (Exception e) {
throw new BuilderException("Error invoking SqlProvider method ("
+ providerType.getName() + "." + providerMethod.getName()
+ "). Cause: " + e, e);
}
}
//获得方法参数
private Object[] extractProviderMethodArguments(Object parameterObject) {
if (providerContext != null) {
Object[] args = new Object[2];
args[providerContextIndex == 0 ? 1 : 0] = parameterObject;
args[providerContextIndex] = providerContext;
return args;
} else {
return new Object[] { parameterObject };
}
}
private Object[] extractProviderMethodArguments(Map<String, Object> params, String[] argumentNames) {
Object[] args = new Object[argumentNames.length];
for (int i = 0; i < args.length; i++) {
if (providerContextIndex != null && providerContextIndex == i) {
args[i] = providerContext;
} else {
args[i] = params.get(argumentNames[i]);
}
}
return args;
}
//执行方法,生成SQL
private String invokeProviderMethod(Object... args) throws Exception {
Object targetObject = null;
if (!Modifier.isStatic(providerMethod.getModifiers())) {
targetObject = providerType.newInstance();
}
CharSequence sql = (CharSequence) providerMethod.invoke(targetObject, args);
return sql != null ? sql.toString() : null;
}
private String replacePlaceholder(String sql) {
return PropertyParser.parse(sql, configuration.getVariables());
}
}
ProviderContext ProviderSqlSource的上下文
public final class ProviderContext {
//Mapper接口
private final Class<?> mapperType;
//Mapper的方法
private final Method mapperMethod;
ProviderContext(Class<?> mapperType, Method mapperMethod) {
this.mapperType = mapperType;
this.mapperMethod = mapperMethod;
}
public Class<?> getMapperType() {
return mapperType;
}
public Method getMapperMethod() {
return mapperMethod;
}
}