• mybatis源码分析



    mybatis源码分析:
    分为3个阶段:
    1.解析mybatis-config.xml,构建Configuration对象(入口)
    2.根据Mapper接口生成代理对象
    3.执行Mapper接口的方法,调用代理对象方法,根据接口全类名+方法名 找到 对应xml中namespace+id的sql语句,执行sql,将结果映射成返回的参数类型(反射+属性赋值)

    1.解析mybatis-config.xml,构建Configuration对象(入口):
    String resource = "mybaits-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    1.new XMLConfigBuilder(inputStream, environment, properties);//初始化Configuration对象,并创建XmlConfigBuilder对象
    2.build(parser.parse());
    1.parser.parse();
    parseConfiguration(parser.evalNode("/configuration"));//从mybaits-config.xml主配置文件中拿根节点/configuration ,解析里面的子节点放入Configuration大对象中
    解析节点:properties,settings,typeAliases,plugins,objectFactory,objectWrapperFactory,reflectorFactory,environments,databaseIdProvicer,typeHandlers,mappers
    重点是properties,settings,typeAliaes,plugins,environments,typeHandlers,mappers
    1.propertiesElement(root.evalNode("properties")):解析resource或url,不能同时写这两个选项.
    configuration.setVariables(defaults);
    2.Properties settings = settingsAsProperties(root.evalNode("settings"));
    loadCustomVfs(settings);
    configuration.setVfsImpl(vfsImpl);
    settingsElement(settings);//给configuration中的属性赋值,如configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true)); //cacheEnabled二级缓存的总开关,默认为true
    3.typeAliasesElement(root.evalNode("typeAliases"));
    configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage); //扫描@Alias注解
    4.pluginElement(root.evalNode("plugins"));
    configuration.addInterceptor(interceptorInstance); //InterceptorChain底层是采用ArrayList存interceptor拦截器,ArrayList是有序的先进先出

    5.environmentsElement(root.evalNode("environments"));// 每个environment对应一个SqlSessionFactory
    configuration.setEnvironment(environmentBuilder.build());//主要是dataSource数据源,事务管理transactionManager的配置 ,建造者模式
    6.typeHandlerElement(root.evalNode("typeHandlers"));//数据库字段jdbcType与java属性javaType的 类型映射
    typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
    7.mapperElement(root.evalNode("mappers"));//解析mappers的配置文件,放入configuration。 //mappers中有两种方式定义子节点:1.package 2.mapper中配置resource/url/class 三选一
    configuration.addMappers(mapperPackage);
    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
    mapperParser.parse();//重点
    configurationElement(parser.evalNode("/mapper"));
    builderAssistant.setCurrentNamespace(namespace);//命名空间,MapperBuilderAssistant来处理
    cacheRefElement(context.evalNode("cache-ref"));//二级缓存的引用
    cacheElement(context.evalNode("cache"));//二级缓存,<cache type="" eviction="" flushInterval="" size="" blocking="" readOnly="" />
    parameterMapElement(context.evalNodes("/mapper/parameterMap"));//入参parameterMap
    resultMapElements(context.evalNodes("/mapper/resultMap"));//返回参数resultMap
    sqlElement(context.evalNodes("/mapper/sql"));//sql标签
    buildStatementFromContext(context.evalNodes("select|insert|update|delete"));//解析真正的增删改查语句
    final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
    statementParser.parseStatementNode();//一级缓存开关:在select标签中:useCache,flushCache 。 主键配置useGeneratedKeys,keyProperty 或 selectKey

    2.build(parser.parse());
    new DefaultSqlSessionFactory(config);//创建默认的DefaultSqlSessionFactory。


    mybaits三个重要的类:XmlConfigBuilder,XmlMapperBuilder,XmlStatementBuilder
    XmlConfigBuilder解析主配置文件Mybatis-config.xml; XmlMapperBuilder解析业务映射文件*Mapper.xml; XmlStatementBuilder解析增删改查语句

    2.根据Mapper接口生成代理对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    new DefaultSqlSession(configuration, executor, autoCommit);//默认的executor为SimpleExecutor,默认自动提交autoCommit为false
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    configuration.<T>getMapper(type, this);
    mapperRegistry.getMapper(type, sqlSession);
    mapperProxyFactory.newInstance(sqlSession);
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

    3.执行Mapper接口的方法,调用代理对象方法
    List<User> users = mapper.queryList();
    MapperProxy.invoke();
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);//根据command.getType()的类型,选择要执行的增删改查语句,以下以select为例
    result = executeForMany(sqlSession, args);
    result = sqlSession.<E>selectList(command.getName(), param);
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
    return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); //最终是调用Executor的query方法
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
    list = resultHandler == null ? (List<E>) localCache.getObject(key) : null; //先从缓存中查询,如果有直接返回,如果没有就查数据库
    handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); //从缓存中查询
    list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);//从数据库查询
    list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);//Executor的实现类有SimpleExecutor,ReuseExecutor,BatchExecutor,默认是SimpleExecutor
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
    stmt = prepareStatement(handler, ms.getStatementLog());//创建连接Connection,创建Statement/PrepareStatement,对参数进行赋值
    Connection connection = getConnection(statementLog);//创建Connection
    stmt = handler.prepare(connection, transaction.getTimeout());//创建Statement/PrepareStatement
    handler.parameterize(stmt);//对参数进行赋值
    return handler.<E>query(stmt, resultHandler);//获取sql,执行sql,处理结果集resultSet
    String sql = boundSql.getSql();
    statement.execute(sql);
    return resultSetHandler.<E>handleResultSets(statement);


  • 相关阅读:
    Java 装箱、拆箱 包装器
    Oracle decode函数 除数为零
    Java并发编程之ConcurrentHashMap
    MessageDigest 类
    Java中关于OOM的场景及解决方法
    Memcached的一些知识
    Solr导入数据库数据
    前端学习笔记(zepto或jquery)——对li标签的相关操作(二)
    前端学习笔记(zepto或jquery)——对li标签的相关操作(一)
    DES加密深度优化——随机生成加密字符串
  • 原文地址:https://www.cnblogs.com/lookupthesky/p/10510821.html
Copyright © 2020-2023  润新知