mybatis_helloworld(2)_源码

摘录自:http://blog.csdn.net/y172158950/article/details/16982123

在helloworld(1)中,分析了insert一条数据的流程,现在分析下源码:

  1. public static void main(String args[]) throws IOException {
  2. String resource = "com/test/configuration.xml";//获得xml(Mybatis)数据库连接的连接
  3. Reader reader = Resources.getResourceAsReader(resource);//读取里面的文件
  4. SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder()
  5. .build(reader);//创建session工厂
  6. SqlSession session = sessionFactory.openSession();//打开session
  7. new Test1().insert(session);
  8. }

1. XML文件资源的获取

a)包路径:org.apache.ibatis.io

b)Resources类:定义了一系列的静态方法,用于获取资源(ClassLoader,URL,InputStream,Read,File,Properties,Charset)

c)我们用到的getResourceAsReader,getResourceAsStream方法

  1. <p>    public static Reader getResourceAsReader(String resource)
  2. throws IOException
  3. {
  4. Reader reader;</p><p>·       //利用InputStream构造Reader
  5. if(charset == null)
  6. reader = new InputStreamReader(getResourceAsStream(resource));
  7. else
  8. reader = new InputStreamReader(getResourceAsStream(resource), charset);
  9. return reader;
  10. }</p><p>   </p><p>    public static InputStream getResourceAsStream(String resource)
  11. throws IOException
  12. {</p><p>        //调用重载方法
  13. return getResourceAsStream(null, resource);
  14. }</p><p> </p><p>    public static InputStream getResourceAsStream(ClassLoader loader, String resource)
  15. throws IOException
  16. {</p><p>        //调用ClassLoaderWrapper类的方法,利用ClassLoader获取资源
  17. InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
  18. if(in == null)
  19. throw new IOException((new StringBuilder()).append("Could not find resource ").append(resource).toString());
  20. else
  21. return in;
  22. }</p>

d)ClassLoaderWrapper类:封装了一个ClassLoader数组,通过ClassLoader获取资源

e)我们用到的getResourceAsStream,getClassLoaders方法

  1. public InputStream getResourceAsStream(String resource, ClassLoader classLoader)
  2. {
  3. return getResourceAsStream(resource, getClassLoaders(classLoader));
  4. }
  5. ClassLoader[] getClassLoaders(ClassLoader classLoader)
  6. {
  7. return (new ClassLoader[] {  //构建新的ClassLoader列表,包含用户创建及默认
  8. classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(),           systemClassLoader});
  9. }
  10. InputStream getResourceAsStream(String resource, ClassLoader classLoader[])
  11. {
  12. ClassLoader arr$[] = classLoader;
  13. int len$ = arr$.length;
  14. for(int i$ = 0; i$ < len$; i$++)    //遍历ClassLoader数组,当某一个Loader成功构建资源则返回
  15. {
  16. ClassLoader cl = arr$[i$];
  17. if(null == cl)
  18. continue;
  19. InputStream returnValue = cl.getResourceAsStream(resource);
  20. if(null == returnValue)
  21. returnValue = cl.getResourceAsStream((new StringBuilder()).append("/").append(resource).toString());
  22. if(null != returnValue)
  23. return returnValue;
  24. }
  25. return null;
  26. }

2. 构建SqlSessionFactory,初始化资源

a) SqlSessionFactory接口介绍

  1. public interface SqlSessionFactory
  2. {
  3. //定义了一系列获取Session的方法,获取Configuration的方法
  4. public abstract SqlSession openSession();
  5. public abstract SqlSession openSession(boolean flag);
  6. public abstract SqlSession openSession(Connection connection);
  7. public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);
  8. public abstract SqlSession openSession(ExecutorType executortype);
  9. public abstract SqlSession openSession(ExecutorType executortype, boolean flag);
  10. public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);
  11. public abstract SqlSession openSession(ExecutorType executortype, Connection connection);
  12. public abstract Configuration getConfiguration();
  13. }

b) SqlSessionFactory接口构建

i. SqlSessionFactoryBuilder类:构建SqlSessionFactory

ii. 我们使用的方法:build

  1. public SqlSessionFactory build(Reader reader)
  2. {
  3. //调用重载方法
  4. return build(reader, null, null);
  5. }
  6. public SqlSessionFactory build(Reader reader, String environment, Properties properties)
  7. {
  8. try
  9. {
  10. SqlSessionFactory sqlsessionfactory;
  11. try
  12. {
  13. //根据reader封装XMLConfig相关信息
  14. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  15. //调用重载方法
  16. sqlsessionfactory = build(parser.parse());
  17. }
  18. catch(Exception e)
  19. {
  20. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  21. }
  22. return sqlsessionfactory;
  23. }
  24. finally
  25. {
  26. ErrorContext.instance().reset();
  27. try
  28. {
  29. reader.close();
  30. }
  31. catch(IOException e) { }
  32. }
  33. }
  34. public SqlSessionFactory build(Configuration config)
  35. {
  36. //依据配置信息构建默认的SqlSessionFactory实现
  37. return new DefaultSqlSessionFactory(config);
  38. }

c) XMLConfigBuilder类:解析XML配置文件

i. 用到的主要方法:parse,parseConfiguration(就是按XML结构顺序解析,分别获取配置[SAX解析]);将数据封装到父类的configuration对象中

  1. public Configuration parse()
  2. {
  3. if(parsed)
  4. {
  5. throw new BuilderException("Each MapperConfigParser can only be used once.");
  6. } else
  7. {
  8. parsed = true;
  9. parseConfiguration(parser.evalNode("/configuration"));   //XML文件的根目录
  10. return configuration;
  11. }
  12. }
  13. private void parseConfiguration(XNode root)
  14. {
  15. try
  16. {
  17. typeAliasesElement(root.evalNode("typeAliases"));    //解析typeAliases
  18. pluginElement(root.evalNode("plugins"));
  19. objectFactoryElement(root.evalNode("objectFactory"));
  20. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  21. propertiesElement(root.evalNode("properties"));
  22. settingsElement(root.evalNode("settings"));
  23. environmentsElement(root.evalNode("environments"));   //数据库配置
  24. typeHandlerElement(root.evalNode("typeHandlers"));
  25. mapperElement(root.evalNode("mappers"));    //解析sql语句配置文件
  26. }
  27. catch(Exception e)
  28. {
  29. throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);
  30. }
  31. }

d)Configuration类:基本就是封装一系列的数据;看一下成员变量

  1. protected Environment environment;
  2. protected boolean lazyLoadingEnabled;
  3. protected boolean aggressiveLazyLoading;
  4. protected boolean multipleResultSetsEnabled;
  5. protected boolean useGeneratedKeys;
  6. protected boolean useColumnLabel;
  7. protected boolean cacheEnabled;
  8. protected Integer defaultStatementTimeout;
  9. protected ExecutorType defaultExecutorType;
  10. protected AutoMappingBehavior autoMappingBehavior;
  11. protected Properties variables;
  12. protected ObjectFactory objectFactory;
  13. protected ObjectWrapperFactory objectWrapperFactory;
  14. protected MapperRegistry mapperRegistry;
  15. protected final InterceptorChain interceptorChain;
  16. protected final TypeHandlerRegistry typeHandlerRegistry;
  17. protected final TypeAliasRegistry typeAliasRegistry;
  18. protected final Map mappedStatements;
  19. protected final Map caches;
  20. protected final Map resultMaps;
  21. protected final Map parameterMaps;
  22. protected final Map keyGenerators;
  23. protected final Set loadedResources;
  24. protected final Map sqlFragments;
  25. protected final Collection incompleteStatements;
  26. protected final Collection incompleteCacheRefs;
  27. protected final Map cacheRefMap;

e)DefaultSqlSessionFactory类:SqlSessionFactory接口实现类,并持有一个Configuration对象;我们实现获取SqlSeesion对象应用的此类的方法。

3. 回过头来,再看看SqlSession session = sessionFactory.openSession();这行代码的实现

  1. public SqlSession openSession()
  2. {
  3. return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  4. }
  5. private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)
  6. {
  7. Connection connection = null;
  8. try
  9. {
  10. DefaultSqlSession defaultsqlsession;
  11. try
  12. {
  13. Environment environment = configuration.getEnvironment();
  14. //获取javax.sql.DataSource
  15. DataSource dataSource = getDataSourceFromEnvironment(environment);
  16. TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
  17. //获取java.sql.Connection
  18. connection = dataSource.getConnection();
  19. if(level != null)
  20. connection.setTransactionIsolation(level.getLevel());
  21. connection = wrapConnection(connection);
  22. //一系列的封装,把Connection包装成了DefaultSqlSession(SqlSession的实现类)
  23. org.apache.ibatis.transaction.Transaction tx = transactionFactory.newTransaction(connection, autoCommit);
  24. org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
  25. defaultsqlsession = new DefaultSqlSession(configuration, executor, autoCommit);
  26. }
  27. catch(Exception e)
  28. {
  29. closeConnection(connection);
  30. throw ExceptionFactory.wrapException((new StringBuilder()).append("Error opening session.  Cause: ").append(e).toString(), e);
  31. }
  32. return defaultsqlsession;
  33. }
  34. finally
  35. {
  36. ErrorContext.instance().reset();
  37. }
  38. }

4. insert数据的实现

  1. public int insert(String statement, Object parameter)
  2. {
  3. return update(statement, parameter);
  4. }
  5. public int update(String statement, Object parameter)
  6. {
  7. try
  8. {
  9. int i;
  10. try
  11. {
  12. dirty = true;
  13. //根据Mapper.xml配置文件中的id找到Sql语句
  14. org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);
  15. //这个执行器是不是见过?构建DefaultSqlSession时传过来的
  16. // org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);
  17. i = executor.update(ms, wrapCollection(parameter));
  18. }
  19. catch(Exception e)
  20. {
  21. throw ExceptionFactory.wrapException((new StringBuilder()).append("Error updating database.  Cause: ").append(e).toString(), e);
  22. }
  23. return i;
  24. }
  25. finally
  26. {
  27. ErrorContext.instance().reset();
  28. }
  29. }

a) 找一下executor,看看其update方法

i. 调用哪个executor?

  1. public Executor newExecutor(Transaction transaction, ExecutorType executorType)
  2. {
  3. executorType = executorType != null ? executorType : defaultExecutorType;  //我们使用的是默认的Type(SIMPLE)
  4. executorType = executorType != null ? executorType : ExecutorType.SIMPLE;
  5. Executor executor;
  6. if(ExecutorType.BATCH == executorType)
  7. executor = new BatchExecutor(this, transaction);
  8. else
  9. if(ExecutorType.REUSE == executorType)
  10. executor = new ReuseExecutor(this, transaction);
  11. else
  12. executor = new SimpleExecutor(this, transaction);
  13. if(cacheEnabled)
  14. executor = new CachingExecutor(executor);
  15. executor = (Executor)interceptorChain.pluginAll(executor);
  16. return executor;
  17. }

ii. SimpleExecutor的update方法实现

  1. //父类BaseExecutor的update方法,调用了doUpdate方法
  2. public int update(MappedStatement ms, Object parameter)
  3. throws SQLException
  4. {
  5. ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
  6. if(closed)
  7. {
  8. throw new ExecutorException("Executor was closed.");
  9. } else
  10. {
  11. clearLocalCache();
  12. return doUpdate(ms, parameter);
  13. }
  14. }
  15. //子类SimpleExecutor重写了doUpdate方法
  16. public int doUpdate(MappedStatement ms, Object parameter)
  17. throws SQLException
  18. {
  19. //java.sql.Statement
  20. Statement stmt = null;
  21. int i;
  22. try
  23. {
  24. Configuration configuration = ms.getConfiguration();
  25. StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);
  26. //大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)
  27. stmt = prepareStatement(handler);
  28. i = handler.update(stmt);
  29. }
  30. finally
  31. {
  32. closeStatement(stmt);
  33. }
  34. return i;
  35. }

看了一回源码,也感觉高端大气上档次了,下次画个图

上一篇:Git 分支管理和冲突解决


下一篇:npm http-server Dockerfile alpine 微容器,袖珍体积,解决时区问题