结合Mybatis源码说说sqlSession创建流程和从中用到的一些设计模式

  1. 根据下面这行代码,结合Mybatis源码说说sqlSession创建流程和从中用到的一些设计模式:

    1 UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    1. 读取配置文件,生成Configuration对象,其中包含数据源、事务、mapper文件资源以及影响数据库行为属性settings;

    2. SqlSessionFactoryBuilder通过读取Configuration对象,生成SqlSessionFactory(构建者模式);

       1 public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
       2   SqlSessionFactory var5;
       3   try {
       4     XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
       5     var5 = this.build(parser.parse());
       6   } catch (Exception var14) {
       7     throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
       8   } finally {
       9     ErrorContext.instance().reset();
      10 
      11     try {
      12       reader.close();
      13     } catch (IOException var13) {
      14     }
      15 
      16   }
      17 
      18   return var5;
      19 }
       1 private void bindMapperForNamespace() {
       2         String namespace = this.builderAssistant.getCurrentNamespace();
       3         if (namespace != null) {
       4             Class boundType = null;
       5 
       6             try {
       7                 boundType = Resources.classForName(namespace);
       8             } catch (ClassNotFoundException var4) {
       9             }
      10 
      11             if (boundType != null && !this.configuration.hasMapper(boundType)) {
      12                 this.configuration.addLoadedResource("namespace:" + namespace);
      13                 this.configuration.addMapper(boundType);
      14             }
      15         }
      16 
      17  }
      1 public SqlSessionFactory build(Configuration config) {
      2      return new DefaultSqlSessionFactory(config);
      3  }
    3. 在调用build()方法时,通过XMLConfigBuilder类bindMapperForNamespace()方法,将Mapper接口注册到MapperRegistry类的一个HashMap属性中,key=Mapper.class,value=创建当前Mapper的工厂;

    4. 通过SqlSessionFactory生成SqlSession实例对象(工厂模式);

    5. sqlSession通过getMapper()方法拿到代理对象(代理模式),运用了JDK动态代理,生成了目标Mapper对象的代理对象;

    6. 通过MapperProxyFactory工厂,生成动态代理的代理类是MapperProxy(工厂模式),实现了InvocationHandler接口,对invoke()方法进行了包装,将非Object类的方法进行了增强,包装成MapperMethod,最后执行execute()方法完成sql增删改查的操作。

      public Object invoke(Object proxy, Method method, Object[] args) 
           throws Throwable {
           try {
               //如果method方法是来自Object的方法,那么直接执行,无需增强;
               //意思是假如我们执行的是toString()方法,是不需要增强的。
               if (Object.class.equals(method.getDeclaringClass())) {
                   return method.invoke(this, args);
               }
               if (this.isDefaultMethod(method)) {
                   return this.invokeDefaultMethod(proxy, method, args);
               }
           } catch (Throwable var5) {
               throw ExceptionUtil.unwrapThrowable(var5);
           }
           //做了缓存
           MapperMethod mapperMethod = this.cachedMapperMethod(method);
           //执行增删改查操作
           return mapperMethod.execute(this.sqlSession, args);
       }
posted @ 2020-03-11 10:46  from威仔  阅读(482)  评论(0编辑  收藏  举报