MyBatis源码解析--加载流程(5)

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;
  }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值