源码分析----Mybatis
一、源码分析
1、创建会话工厂
1 | SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); |
·1.1 调用了parse方法,将mybatis配置文件的信息全部解析到一个Configuration对象中(包扩mybatis启动配置信息,数据源,Mapper.xml(sql语句))
1 2 3 4 5 6 7 8 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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对象中)
1 2 3 4 | builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); |
第一步结束后,最终返回一个 DefaultSqlSessionFactory(保存了Configuration,里面最重要的两个属性)
1 2 3 4 | public class Configuration { protected MapperRegistry mapperRegistry = new MapperRegistry( this ); //用于生产mapper代理 protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>( "Mapped Statements collection" ); } |
2、通过工厂得到SqlSession
1 | SqlSession sqlSession = sqlSessionFactory.openSession(); |
2.1
1 | return openSessionFromDataSource(configuration.getDefaultExecutorType(), null , false ); |
2.1.1 返回一个 defaultExecutorType = ExecutorType.SIMPLE(默认),还要其他的(BATCH,REUSE),后面会根据这个创建不同的 Executor
1 | configuration.getDefaultExecutorType() |
2.1.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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是一个接口,规定了增删改查的所有的方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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
1 2 3 4 5 6 7 8 | 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、获取代理对象,代理对象去执行增删改查
1 | UserDao mapper = sqlSession.getMapper(UserDao. class ); |
3.1
1 2 3 | public <T> T getMapper(Class<T> type) { return configuration.<T>getMapper(type, this ); } |
3.1.1
1 2 3 | public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return mapperRegistry.getMapper(type, sqlSession); } |
3.1.1.1
1 2 3 4 5 6 7 8 9 10 11 12 | @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
1 | mapperProxyFactory.newInstance(sqlSession); |
3.1.1.1.1.1 public class MapperProxy<T> implements InvocationHandler, Serializable (MapperProxy就是一个InvocationHander)
1 2 3 4 | 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 最终创建代理
1 2 3 | protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步