首页 > 其他 > 详细

mybatis原理分析

时间:2019-12-09 23:23:03      阅读:95      评论:0      收藏:0      [点我收藏+]

1:mybatis首先构建SqlSessionFactory,这个工厂主要就是初始化与数据库操作有关的上下文信息。会收集xml中的配置,如environment,datasource,transactionManager,setting配置等等,而默认构建出来的是DefaultSqlSessionFactory。

在mybatis最重要的配置节点就是和sql执行相关的mappers配置节点:

mybatis的mappers节点下可配置mapper和package:
(1)如果配置package首先会扫描接口,将接口中的每一个方法扫描到,并获取注解,“接口方法的全名称”和对应的“mappedStatement”对象(mappedStatement实际就是sql配置节点各个属性封装成的java对象)放入strictMap中。
(2)如果配置了mapper则,resources属性,url属性,class属性只能选择一个,因为源码只允许写一个,否则会抛出异常。

mybatis实际生产sql的时候是有两种方式,一个是动态sql一个是静态sql:
(1)动态sql中mybatis解析器会有一个标识,如果开头是“${”,结尾是“}”,则认为是动态sql。
(2)如果是静态sql那么加入,mappedStatement中的sqlResource就是将“#{}”替换成了“?”占位符的sql样子。

2:当SqlSessionFactory创建完成以后就会通过openSession方法获得一个session,默认情况下也是获取了一个DefaultSqlSession,er该sqlsession并没有数据库打开链接之类的行为,而是存储了一些信息,比如“sql执行器”,“配置信息configuration”,以及事务是否自动提交。

tx =transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);

3:核心方法通过getMapper获取实现了接口的代理对象,通过jdk动态代理方式。

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

 4:MapperProxy是动态代理的核心方法它继承自InvocationHandler,而获取对应的Mapper类以后实际执行的方法就是MapperProxy的invok方法

@Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

@UsesJava7
  private Object invokeDefaultMethod(Object proxy, Method method, Object[] args)
      throws Throwable {
    final Constructor<MethodHandles.Lookup> constructor = MethodHandles.Lookup.class
        .getDeclaredConstructor(Class.class, int.class);
    if (!constructor.isAccessible()) {
      constructor.setAccessible(true);
    }
    final Class<?> declaringClass = method.getDeclaringClass();
    return constructor
        .newInstance(declaringClass,
            MethodHandles.Lookup.PRIVATE | MethodHandles.Lookup.PROTECTED
                | MethodHandles.Lookup.PACKAGE | MethodHandles.Lookup.PUBLIC)
        .unreflectSpecial(method, declaringClass).bindTo(proxy).invokeWithArguments(args);
  }

 

mybatis原理分析

原文:https://www.cnblogs.com/zzq-include/p/12013792.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!