getSqlSessionFactory
1.new SqlSessionFactoryBuilder().bulid(全局配置文件的流in)
2.build(in) 进入build(in)
3.parser = new XMLconfigurationBuilder(in) 创建解析器解析 全局配置文件
build(parser.parse()) 进入parse() 方法
4.parse()最后返回的 是 configuration
parseConfiguration(parse.evalNode("/configuration")) 解析全局配置文件configuration节点
5.解析每一个标签,set configuration
6.mapperParser = new XMLMappedBuilder(mapper.xml的 流 )
7.解析 mapper.xml,并且保存在configuration中,并且将mapper.xml中crud标签的每一个标签都解析出来
封装成一个mappedStatement,并将它add configuration
(一个mappedStatnebt代表一个crud标签的 详细信息)
8.返回configuration build(parser.parse()) 结束
9.build(in),结束返回一个 new DefaultSqlSessionFactory(configuration)
返回一个sqlSessionFactory
10.configuration中的两个重要信息
1.mapperStatement(保存每一个mapper.xml 中的 每一个crud的标签信息)
2.mapperRegister 中有一个knowMappers(保存了 每一个 mapper.xml 对应的 接口信息 mapperProxyFactory)
用它可以拿到,mapperProxy
openSession()
1.return openSessionFromDataSource(configuration.getDefalutExecutorType,...)
getDefaultExecutorType 拿到执行器的类型
默认是Simple,还有 REUSE(可复用的执行器),BATCH(可批量操作的执行器)
2.进入 openSessionFromDataSource
1.configuration.getEnvironment()
configuration.getTransation()
获得 全局配置文件的 环境,事务等信息
2.Executor executor = configuration.newExecutor(tx,execType) 四大对象之一
默认拿到的 是 SimpleExecutor(根据 exeTpye 的值 创建不同的 executor)
下面都是对 executor的 封装
3.if(cacheEnabled) 是否配置了二级缓存
若是,将executor包装成 cachingExecutor
executor = new CachingExecutor(executor)
包装的好处:在查询之前先用cachingExecutor查询缓存,然后再用executor去查询
4.executor = (Executor) interceptorChain.piuginAll(executor)
这是最终的executor,拦截器链连接executor,然后用每一个拦截器包装executor
最终返回executor
5.return DefalutSqlSession(configuration.executor,autoCommit)
最终返回一个defalutSqlSession(包含 configuration,和 executor)
session.getMapper 获得代理对象
1.session.getMapper(mapper.class)
2.进入这个方法,return configuration.getMapper(mapper.class,this),this代表session
3.进入这个方法,return mapperRegister.getMapper(mapper.class,sqlSession)
4.进入这个方法,先拿到 mapperProxyFactory
MapperProxyFactory<T> mapperProxyFactory =(MapperProxyFactory<T>) knowMappers.get(mapperType)
根据接口的类型,拿到对应的mapperProxyFactory
5.return mapperProxyFactory.newInstance(sqlSession)
1.先拿到 mapperProxy 这是InvocationHander,里面包含接口,接口方法,sqlSession,他不是代理对象
2. return newInstance(mapperProxy) 进入这个方法
2.return (T)Proxy.newProxyInstance(),创建mapperProxy的代理对象
6.最终返回,mapperProxy的代理对象
mapper执行方法
1.MapperProxy的invoke(Object proxy,Method method,Object[] args)
1.把 method 包装成 MapperMethod(Mybatis可以识别的)
MapperMethod里面有 sqlCommand属性 和 MethodSignature属性
2.method.execute(sqlSession,args)
1.判断sql的类型 command的类型
2.method.converArgsCommandParam(args)
3.调用sqlSession.select(String statement,params) statement就是 mapperStatement的 id
1.mapperStatement ms = configuration.getMapperStatement(statement)
2.return executor.query(ms,parameter,......)
进入 executor.query
1.BoundSql boundSql = ms.getBoundSql(param) boundSql包含了sql语句的详情
2.创建二级缓存的key CacheKey key
3.return executor.query(ms,param,boundsql,ley......)
1.获取二级缓存 cache(是整体的二级缓存,先拿到后面在去取值)
2.executor.query(ms,param.....),这个executor和前面两个不一样
这个是解封装后的,simpleExecutor
1.cache.getObject(key) 先从二级缓存拿,没有的话
2.localcache.getObject(key) 从一级缓存中拿,没有的话
3.queryFromDatabase(ms,param....)
1.localcache.putObject(key,占位符)
2.list = doQuery(ms....) 查出数据
3.localcache.putObject(key,list)
进入doQuery(ms..)
1.声明 Statment stms = null;
2.拿取 mapperStatment的配置信息 config
3.StatementHandler handler = config.newStatementHandler() 创建 statementHandler
进入newStatementHandler()
1.StatementHandler handler = new RoutingStatementHandler() 创建statementHandler
1.ms.getStatementType 默认 preparedStatement
2.new preparedStatementHandler()
2.和 executor一样,handler创建出来,得经过 拦截器链的封装获得 封装后的 handler
3.handler获取完成
(注意,在创建statementHandler的同时构造器,也创建了ParameterHandler,和ResultSetHandler)
4.用statementHandler创建一个 prepareStatment赋值给stmt
stmt = prepareStatement(handler,ms...)
1.获取连接
2.参数预编译以及参数set进入sql语句
1.获取prepareStatement的时候进行了预编译
2.用ParameterHandler给 预编译后的sql语句 填充占位符
期间使用TypeHandler 来做类型转换
5.return handler.query(stmt,resultHandler) 执行sql返回回结果集
最终是 stmt来完成执行sql,并且用resultSetHandler来封装结果集
结果集的封装也要用到TypeHandler做映射
sqlSessionFactory(包含configuration)
sqlSession(包含了configuration,executor)
mapperProxy(包含sqlSession),他是invocationHandler,不是mapper接收的代理对象,执行mapper在执行的时候会跳到mapperProxy的invoke方法中去
四大对象的创建后,都经过了interceptchain拦截器链的包装,形成新的对象
prepareStatement在获取的时候就进行了预编译,以及用parameterHandler 填充了占位符