• Executor
  • ParameterHandler
  • ResultSetHandler
  • StatementHandler

    8.1 拦截器接口介绍

    1. public interface Interceptor {
    2. Object intercept(Invocation var1) throws Throwable;
    3. Object plugin(Object target);
    4. void setProperties(Properties var1);
    5. }

    setProperties用来传递插件的参数,可以通过参数来改变插件的行为
    参数值传递:

    1. <plugins>
    2. <plugin interceptor="com.ql.simple.plugin.***INterceptor">
    3. <property name="prop1" value="value1"/>
    4. <property name="prop2" value="value2"/>
    5. </plugin>
    6. </plugins>

    plugin方法参数target就要拦截器要拦截的对象,该方法会在创建被拦截的接口实现类时被调用,只需要调用MyBatis提供的Plugin类的wrap静态方法就可以通过java的动态代理拦截目标对象

    1. @Overrride
    2. public Object plugin(Object target){
    3. return Plugin.wrap(target, this);
    4. }

    wrap方法会自动判断拦截器的前面和被拦截器对象的接口是否匹配,只有匹配的情况下才会使用动态代理拦截目标对象,因此上面不用做额外的逻辑判断

intercept是MyBatis运行时要执行的拦截方法:

  1. @Override
  2. public Object intercept(Invocation invocation) throws Throwable {
  3. Object target = invocation.getTarget();
  4. Method method = invocation.getMethod();
  5. Object[] args = invocation.getArgs();
  6. Object result = invocation.proceed();
  7. return result;
  8. }

invocation.proceed();执行被拦截对象真正的方法

8.2 拦截器签名介绍

  • @Intercepts
  • @Signature

用来配置拦截器要拦截的接口的方法

  1. @Intercepts({
  2. @Signature(
  3. type = ResultSetHandler.class,
  4. method = "handleResultSets",
  5. args = {Statement.class})
  6. })
  7. public class DemoInterceptor implements Interceptor {

8.2.1 Executor接口

  • update
  • query
  • queryCursor
  • flushStatements
  • commit
  • rollback
  • getTransaction
  • close
  • isClosed

    8.2.2 ParameterHandler

    8.3 下划线键值转小写驼峰形式插件

    1. @Intercepts(@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}))
    2. @SuppressWarnings({"unchecked", "rawtypes"})
    3. public class CameHumpInterceptor implements Interceptor {
    4. @Override
    5. public Object intercept(Invocation invocation) throws Throwable {
    6. // 先执行得到结果,再对结果进行处理
    7. List<Object> list = (List<Object>) invocation.proceed();
    8. for (Object o : list) {
    9. // 如果结果是Map类型,就对Map的key进行转换
    10. if (o instanceof Map) {
    11. processMap((Map) o);
    12. }else {
    13. break;
    14. }
    15. }
    16. return list;
    17. }
    18. private void processMap(Map<String, Object> map) {
    19. Set<String> keySet = new HashSet<>(map.keySet());
    20. for (String key : keySet) {
    21. // 将以大写开头的字符串转换为小写,如果包含下划线也会处理为驼峰
    22. // 此处只通过这两个简单的表示来判断是否进行转换
    23. if ((key.charAt(0) >= 'A' && key.indexOf(0) <= 'Z') || key.indexOf("_") >= 0){
    24. Object value = map.get(key);
    25. map.remove(key);
    26. map.put(underlineToCamelhump(key), value);
    27. }
    28. }
    29. }
    30. public static String underlineToCamelhump(String inputString){
    31. StringBuffer sb = new StringBuffer();
    32. boolean nextUpperCase = false;
    33. for (int i = 0; i < inputString.length(); i++) {
    34. char c = inputString.charAt(i);
    35. if (c == '_'){
    36. if (sb.length() > 0) {
    37. nextUpperCase = true;
    38. }
    39. }else {
    40. if (nextUpperCase) {
    41. sb.append(Character.toUpperCase(c));
    42. nextUpperCase = false;
    43. }else {
    44. sb.append(Character.toLowerCase(c));
    45. }
    46. }
    47. }
    48. return sb.toString();
    49. }
    50. @Override
    51. public Object plugin(Object o) {
    52. return Plugin.wrap(o, this);
    53. }
    54. @Override
    55. public void setProperties(Properties properties) {
    56. }
    57. }

    8.4 分页插件