zoukankan      html  css  js  c++  java
  • 源码分析----Mybatis

    一、源码分析

    1、创建会话工厂

    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    

    ·1.1 调用了parse方法,将mybatis配置文件的信息全部解析到一个Configuration对象中(包扩mybatis启动配置信息,数据源,Mapper.xml(sql语句))

      public Configuration parse() {
        if (parsed) {
          throw new BuilderException("Each XMLConfigBuilder can only be used once.");
        }
        parsed = true;
        parseConfiguration(parser.evalNode("/configuration"));
        return configuration;
      }

    1.1.1 解析Mapper.xml

    private void mapperElement(XNode parent) throws Exception {
        if (parent != null) {
          for (XNode child : parent.getChildren()) {
            if ("package".equals(child.getName())) {
              String mapperPackage = child.getStringAttribute("name");
              configuration.addMappers(mapperPackage);
            } else {
              String resource = child.getStringAttribute("resource");
              String url = child.getStringAttribute("url");
              String mapperClass = child.getStringAttribute("class");
              if (resource != null && url == null && mapperClass == null) {
                ErrorContext.instance().resource(resource);
                InputStream inputStream = Resources.getResourceAsStream(resource);
                XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
                mapperParser.parse();
              } else if (resource == null && url != null && mapperClass == null) {
                ErrorContext.instance().resource(url);
                InputStream inputStream = Resources.getUrlAsStream(url);
                XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
    
               //将解析mybatis配置中的mapper节点,里面将解析mapper.xml中的sql
                mapperParser.parse();
              } else if (resource == null && url == null && mapperClass != null) {
                Class<?> mapperInterface = Resources.classForName(mapperClass);
                configuration.addMapper(mapperInterface);
              } else {
                throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
              }
            }
          }
        }
      }
    

    1.1.1.1 里面执行了(将sql信息封装到了MapperedStatement中(一个MapperedStatement代表了增删改查的详细信息),MappedStatement封装在了Configuration对象中)

    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
            fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
            resultSetTypeEnum, flushCache, useCache, resultOrdered, 
            keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);

    第一步结束后,最终返回一个 DefaultSqlSessionFactory(保存了Configuration,里面最重要的两个属性

    public class Configuration {
        protected MapperRegistry mapperRegistry = new MapperRegistry(this); //用于生产mapper代理
        protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection"); 
    }
    

      

    2、通过工厂得到SqlSession

    SqlSession sqlSession = sqlSessionFactory.openSession();  
    

    2.1

    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
    

    2.1.1 返回一个 defaultExecutorType = ExecutorType.SIMPLE(默认),还要其他的(BATCH,REUSE),后面会根据这个创建不同的 Executor

    configuration.getDefaultExecutorType()
    

    2.1.2

      private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        try {
        //获取环境信息
          final Environment environment = configuration.getEnvironment();
          final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
          tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
          
        //创建4大对象之一的Executor
        final Executor executor = configuration.newExecutor(tx, execType);
        
        //返回DefaultSqlSession(里面包含配置信息,和执行器)
          return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
          closeTransaction(tx); // may have fetched a connection so lets call close()
          throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
          ErrorContext.instance().reset();
        }
      }

    2.1.2.1 根据 ExecutorType,创建不同的执行器,Executor是一个接口,规定了增删改查的所有的方法;

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
          executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
          executor = new ReuseExecutor(this, transaction);
        } else {
          executor = new SimpleExecutor(this, transaction);
        }
      //是否配置了二级缓存
        if (cacheEnabled) {
          executor = new CachingExecutor(executor);
        }
    
        //执行拦截器链(interceptorChain封装了拦截器列表),非常重要,每一个executory的创建都要被拦截
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
      }  

    2.1.2.1.1

      private final List<Interceptor> interceptors = new ArrayList<Interceptor>();
    
      public Object pluginAll(Object target) {
        for (Interceptor interceptor : interceptors) {
          target = interceptor.plugin(target); //执行每一个拦截器的plugin方法,如果没有就跳过
        }
        return target;
      }
    

    第2步主要就是返回了一个 DefaultSqlSession,里面创建了执行器,封装到DefaultSqlSession中

    3、获取代理对象,代理对象去执行增删改查

    UserDao mapper = sqlSession.getMapper(UserDao.class);
    

    3.1

      public <T> T getMapper(Class<T> type) {
        return configuration.<T>getMapper(type, this);
      }
    

    3.1.1

      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        return mapperRegistry.getMapper(type, sqlSession);
      }
    

    3.1.1.1

      @SuppressWarnings("unchecked")
      public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
      //knownMappers通过type,获得代理对象
        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);
        }
      }
    

    3.1.1.1.1

    mapperProxyFactory.newInstance(sqlSession);
    

    3.1.1.1.1.1 public class MapperProxy<T> implements InvocationHandler, Serializable (MapperProxy就是一个InvocationHander)

      public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
      }
    

    3.1.1.1.1.1.1 最终创建代理

      protected T newInstance(MapperProxy<T> mapperProxy) {
        return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
      }
    

      

      

  • 相关阅读:
    postgresql 9.x stream status check
    postgresql 物理备份 tar 命令
    centos 6.8 + postgresql 9.6 + yum 的一些路径
    debian8.2 + postgresql 9.1 + apt-get 的一些路径
    window 2012 上安装 sql server 2005 出错的解决方案
    postgresql 计算时间差的秒数
    centos 6.8 + postgresql 9.6 + pgagent
    postgresql 9.1 查看表和索引的大小
    centos 6.8 + postgresql 9.6 + pg_stat_statements
    centos 6.8 + postgresql 9.6 + file_fdw
  • 原文地址:https://www.cnblogs.com/yanxiaoge/p/11329722.html
Copyright © 2011-2022 走看看