zoukankan      html  css  js  c++  java
  • mybatis源码学习: 动态代理的应用(慢慢改)

      动态代理概述

       在学spring的时候知道使用动态代理实现aop,入门的列子:需要计算所有方法的调用时间。可以每个方法开始和结束都获取当前时间咋办呢。类似这样:

    long current=system.currenttimemillis();
    调用原来的方法
    long last=system.currenttimemillis();

    如果每个方法都人工加入实在有点不爽,动态代理出场了。动态代理利用字节码技在原来对应的类的子节码进行重写,添加对应的逻辑。

    主流的动态代理实现技术主流如下:JDK 和CGLIB,Javassist,ASM  参考这个

    mybatis的应用

      我们知道在mybatis中,我们只要编写mapper的接口和接口对应的mapper.xml ,利用下面方法就可以获取实例和调用方法。(代码来自mybatis3自带测试用例

    BoundBlogMapper mapper = session.getMapper(BoundBlogMapper.class);

    Blog b = mapper.selectBlogWithPostsUsingSubSelect(1);
    assertEquals(1, b.getId());
    session.close();

    这里面的mapper就是利用jdk中的动态代理方式获取的接口BoundBlogMapper的代理类的对象。具体方法自己看。很容易跟踪。jdk动态代理最重要的就是实现

    InvocationHandler接口的处理累。最重调用如下。invoke方法中mapperMethod.execute(sqlSession, args)最重要
     1 public class MapperProxy<T> implements InvocationHandler, Serializable {
     2 
     3   private static final long serialVersionUID = -6424540398559729838L;
     4   private final SqlSession sqlSession;
     5   private final Class<T> mapperInterface;
     6   private final Map<Method, MapperMethod> methodCache;
     7 
     8   public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
     9     this.sqlSession = sqlSession;
    10     this.mapperInterface = mapperInterface;
    11     this.methodCache = methodCache;
    12   }
    13 
    14   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    15     if (Object.class.equals(method.getDeclaringClass())) {
    16       try {
    17         return method.invoke(this, args);
    18       } catch (Throwable t) {
    19         throw ExceptionUtil.unwrapThrowable(t);
    20       }
    21     }
    22     final MapperMethod mapperMethod = cachedMapperMethod(method);
    23     return mapperMethod.execute(sqlSession, args);
    24   }
    25 
    26   private MapperMethod cachedMapperMethod(Method method) {
    27     MapperMethod mapperMethod = methodCache.get(method);
    28     if (mapperMethod == null) {
    29       mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
    30       methodCache.put(method, mapperMethod);
    31     }
    32     return mapperMethod;
    33   }
    34 
    35 }

    根据几种操作类型做不同处理

    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        if (SqlCommandType.INSERT == command.getType()) {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = rowCountResult(sqlSession.insert(command.getName(), param));
        } else if (SqlCommandType.UPDATE == command.getType()) {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = rowCountResult(sqlSession.update(command.getName(), param));
        } else if (SqlCommandType.DELETE == command.getType()) {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = rowCountResult(sqlSession.delete(command.getName(), param));
        } else if (SqlCommandType.SELECT == command.getType()) {
          if (method.returnsVoid() && method.hasResultHandler()) {
            executeWithResultHandler(sqlSession, args);
            result = null;
          } else if (method.returnsMany()) {
            result = executeForMany(sqlSession, args);
          } else if (method.returnsMap()) {
            result = executeForMap(sqlSession, args);
          } else {
            Object param = method.convertArgsToSqlCommandParam(args);
            result = sqlSession.selectOne(command.getName(), param);
          }
        } else if (SqlCommandType.FLUSH == command.getType()) {
            result = sqlSession.flushStatements();
        } else {
          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;
      }

     

      

  • 相关阅读:
    jQuery图片切换插件jquery.cycle.js
    UVA
    FragmentPagerAdapter和FragmentStatePagerAdapter的差别
    更改jdk所用内存空间
    一次性能优化将filter转换
    JSP中文件的上传于下载演示样例
    Diskpart工具应用两则:MBR/GPT分区转换 &amp; 基本/动态磁盘转换
    LDD3之并发和竞态-completion(完毕量)的学习和验证
    二维码的扫描、生成
    输入一行字符,分别统计出包括英文字母、空格、数字和其他字符的个数
  • 原文地址:https://www.cnblogs.com/hansongjiang/p/5664344.html
Copyright © 2011-2022 走看看