策略模式的应用之 MyBatis GenericTokenParser

推荐阅读:策略模式

GenericTokenParser 使用

MyBatis 中有一个 GenericTokenParser 类,它用于解析字符串中的占位符:

public class GenericTokenParser {

  private final String openToken;
  private final String closeToken;
  private final TokenHandler handler;

  public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
    this.openToken = openToken;
    this.closeToken = closeToken;
    this.handler = handler;
  }

  public String parse(String text) {
    // ...
    builder.append(handler.handleToken(expression.toString()));
    // ...
  }
}

可以看到它的构造方法接收三个参数,openToken 和 closeToken 分别是占位符开始和结束的标记,而 handler 是一个 TokenHandler 对象。在 parse 方法中,会调用 handler 的 handleToken 方法对占位符进行处理。

下面是一个使用示例:

ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);

上面的代码能够将 originalSql 中类似于#{userId}这样的占位符替换为?

GenericTokenParser 的 parse 方法,作用是解析占位符,每遇到一个占位符,其都会调用 TokenHandler 的 handleToken 方法对其进行处理。

处理的结果就是使用 handleToken 方法的返回值替换字符串中对应的占位符。下面会看到,ParameterMappingTokenHandler 的返回值就是一个?

TokenHandler 接口

TokenHandler 是一个接口,它只有一个 handleToken 方法,用于返回占位符需要被替换为的值:

public interface TokenHandler {
  String handleToken(String content);
}

ParameterMappingTokenHandler 是一个实现该接口的类,它的返回值是?

@Override
public String handleToken(String content) {
  parameterMappings.add(buildParameterMapping(content));
  return "?";
}

策略模式中有三个部分——策略接口、具体策略、上下文。

在这里,TokenHandler 就是策略接口,ParameterMappingTokenHandler 就是具体的策略,GenericTokenParser 就是上下文。

我们知道,除了#{}占位符,MyBatis 中还有${}占位符。${}参数占位符的解析是在 TextSqlNode 类的 apply() 方法中完成的:

@Override
public boolean apply(DynamicContext context) {
  GenericTokenParser parser = createParser(new BindingTokenParser(context, injectionFilter));
  context.appendSql(parser.parse(text));
  return true;
}

private GenericTokenParser createParser(TokenHandler handler) {
  return new GenericTokenParser("${", "}", handler);
}

可以看到 BindingTokenParser 是 TokenHandler 实现类,其和 ParameterMappingTokenHandler 一样也是具体的策略,作用是将占位符替换为 Mapper 参数值。

posted @ 2025-03-02 20:10  Higurashi-kagome  阅读(28)  评论(0)    收藏  举报