mybatis_helloworld(2)_源码

来源:互联网 发布:录制视频软件 知乎 编辑:程序博客网 时间:2024/06/13 02:51

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

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

1. XML文件资源的获取

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

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

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

  

  public static Reader getResourceAsReader(String resource)        throws IOException    {        Reader reader;

· //利用InputStream构造Reader        if(charset == null)            reader = new InputStreamReader(getResourceAsStream(resource));        else            reader = new InputStreamReader(getResourceAsStream(resource), charset);        return reader;    }

  

  public static InputStream getResourceAsStream(String resource)        throws IOException    {

//调用重载方法        return getResourceAsStream(null, resource);    }

 

    public static InputStream getResourceAsStream(ClassLoader loader, String resource)        throws IOException    {

//调用ClassLoaderWrapper类的方法,利用ClassLoader获取资源        InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);        if(in == null)            throw new IOException((new StringBuilder()).append("Could not find resource ").append(resource).toString());        else            return in;    }

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

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

    public InputStream getResourceAsStream(String resource, ClassLoader classLoader)    {        return getResourceAsStream(resource, getClassLoaders(classLoader));    }    ClassLoader[] getClassLoaders(ClassLoader classLoader)    {        return (new ClassLoader[] {  //构建新的ClassLoader列表,包含用户创建及默认            classLoader, defaultClassLoader, Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), systemClassLoader});    }    InputStream getResourceAsStream(String resource, ClassLoader classLoader[])    {        ClassLoader arr$[] = classLoader;        int len$ = arr$.length;        for(int i$ = 0; i$ < len$; i$++)    //遍历ClassLoader数组,当某一个Loader成功构建资源则返回        {            ClassLoader cl = arr$[i$];            if(null == cl)                continue;            InputStream returnValue = cl.getResourceAsStream(resource);            if(null == returnValue)                returnValue = cl.getResourceAsStream((new StringBuilder()).append("/").append(resource).toString());            if(null != returnValue)                return returnValue;        }        return null;    }

2. 构建SqlSessionFactory,初始化资源

a) SqlSessionFactory接口介绍

public interface SqlSessionFactory{    //定义了一系列获取Session的方法,获取Configuration的方法    public abstract SqlSession openSession();    public abstract SqlSession openSession(boolean flag);    public abstract SqlSession openSession(Connection connection);    public abstract SqlSession openSession(TransactionIsolationLevel transactionisolationlevel);    public abstract SqlSession openSession(ExecutorType executortype);    public abstract SqlSession openSession(ExecutorType executortype, boolean flag);    public abstract SqlSession openSession(ExecutorType executortype, TransactionIsolationLevel transactionisolationlevel);    public abstract SqlSession openSession(ExecutorType executortype, Connection connection);    public abstract Configuration getConfiguration();}

b) SqlSessionFactory接口构建

   i. SqlSessionFactoryBuilder类:构建SqlSessionFactory

   ii. 我们使用的方法:build

public SqlSessionFactory build(Reader reader)    {        //调用重载方法        return build(reader, null, null);    }public SqlSessionFactory build(Reader reader, String environment, Properties properties)    {        try        {            SqlSessionFactory sqlsessionfactory;            try            {                //根据reader封装XMLConfig相关信息                XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);                //调用重载方法                sqlsessionfactory = build(parser.parse());            }            catch(Exception e)            {                throw ExceptionFactory.wrapException("Error building SqlSession.", e);            }            return sqlsessionfactory;        }        finally        {            ErrorContext.instance().reset();            try            {                reader.close();            }            catch(IOException e) { }        }    }        public SqlSessionFactory build(Configuration config)    {        //依据配置信息构建默认的SqlSessionFactory实现        return new DefaultSqlSessionFactory(config);    }

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

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

 public Configuration parse()    {        if(parsed)        {            throw new BuilderException("Each MapperConfigParser can only be used once.");        } else        {            parsed = true;            parseConfiguration(parser.evalNode("/configuration"));   //XML文件的根目录            return configuration;        }    }    private void parseConfiguration(XNode root)    {        try        {            typeAliasesElement(root.evalNode("typeAliases"));    //解析typeAliases            pluginElement(root.evalNode("plugins"));            objectFactoryElement(root.evalNode("objectFactory"));            objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));            propertiesElement(root.evalNode("properties"));            settingsElement(root.evalNode("settings"));            environmentsElement(root.evalNode("environments"));   //数据库配置            typeHandlerElement(root.evalNode("typeHandlers"));                mapperElement(root.evalNode("mappers"));    //解析sql语句配置文件        }        catch(Exception e)        {            throw new BuilderException((new StringBuilder()).append("Error parsing SQL Mapper Configuration. Cause: ").append(e).toString(), e);        }    }

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

protected Environment environment;    protected boolean lazyLoadingEnabled;    protected boolean aggressiveLazyLoading;    protected boolean multipleResultSetsEnabled;    protected boolean useGeneratedKeys;    protected boolean useColumnLabel;    protected boolean cacheEnabled;    protected Integer defaultStatementTimeout;    protected ExecutorType defaultExecutorType;    protected AutoMappingBehavior autoMappingBehavior;    protected Properties variables;    protected ObjectFactory objectFactory;    protected ObjectWrapperFactory objectWrapperFactory;    protected MapperRegistry mapperRegistry;    protected final InterceptorChain interceptorChain;    protected final TypeHandlerRegistry typeHandlerRegistry;    protected final TypeAliasRegistry typeAliasRegistry;    protected final Map mappedStatements;    protected final Map caches;    protected final Map resultMaps;    protected final Map parameterMaps;    protected final Map keyGenerators;    protected final Set loadedResources;    protected final Map sqlFragments;    protected final Collection incompleteStatements;    protected final Collection incompleteCacheRefs;    protected final Map cacheRefMap;

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

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

public SqlSession openSession()    {        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);    }        private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)    {        Connection connection = null;        try        {            DefaultSqlSession defaultsqlsession;            try            {                Environment environment = configuration.getEnvironment();                //获取javax.sql.DataSource                DataSource dataSource = getDataSourceFromEnvironment(environment);                TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);                //获取java.sql.Connection                connection = dataSource.getConnection();                if(level != null)                    connection.setTransactionIsolation(level.getLevel());                                connection = wrapConnection(connection);                //一系列的封装,把Connection包装成了DefaultSqlSession(SqlSession的实现类)                org.apache.ibatis.transaction.Transaction tx = transactionFactory.newTransaction(connection, autoCommit);                org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);                defaultsqlsession = new DefaultSqlSession(configuration, executor, autoCommit);            }            catch(Exception e)            {                closeConnection(connection);                throw ExceptionFactory.wrapException((new StringBuilder()).append("Error opening session.  Cause: ").append(e).toString(), e);            }            return defaultsqlsession;        }        finally        {            ErrorContext.instance().reset();        }    }

4. insert数据的实现

 public int insert(String statement, Object parameter)    {        return update(statement, parameter);    }         public int update(String statement, Object parameter)    {        try        {            int i;            try            {                dirty = true;                //根据Mapper.xml配置文件中的id找到Sql语句                org.apache.ibatis.mapping.MappedStatement ms = configuration.getMappedStatement(statement);                //这个执行器是不是见过?构建DefaultSqlSession时传过来的                // org.apache.ibatis.executor.Executor executor = configuration.newExecutor(tx, execType);                i = executor.update(ms, wrapCollection(parameter));            }            catch(Exception e)            {                throw ExceptionFactory.wrapException((new StringBuilder()).append("Error updating database.  Cause: ").append(e).toString(), e);            }            return i;        }        finally        {            ErrorContext.instance().reset();        }    }

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

   i. 调用哪个executor?

public Executor newExecutor(Transaction transaction, ExecutorType executorType)    {        executorType = executorType != null ? executorType : defaultExecutorType;  //我们使用的是默认的Type(SIMPLE)        executorType = executorType != null ? executorType : ExecutorType.SIMPLE;        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);        executor = (Executor)interceptorChain.pluginAll(executor);        return executor;    }

  ii. SimpleExecutor的update方法实现

//父类BaseExecutor的update方法,调用了doUpdate方法 public int update(MappedStatement ms, Object parameter)        throws SQLException    {        ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());        if(closed)        {            throw new ExecutorException("Executor was closed.");        } else        {            clearLocalCache();            return doUpdate(ms, parameter);        }    }        //子类SimpleExecutor重写了doUpdate方法    public int doUpdate(MappedStatement ms, Object parameter)        throws SQLException    {        //java.sql.Statement        Statement stmt = null;        int i;        try        {            Configuration configuration = ms.getConfiguration();            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null);            //大概就是拼Sql,生成对应的Statement,执行Sql,封装数据了(这块比较复杂,下次再看了)            stmt = prepareStatement(handler);                        i = handler.update(stmt);        }        finally        {            closeStatement(stmt);        }        return i;    }

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

原创粉丝点击