准备工作

Mybatis官网地址:https://blog.mybatis.org/
MyBatis官方文档地址:https://mybatis.org/mybatis-3/
MyBatis源码下载地址:https://mybatis.org/mybatis-3/
可以从Git上面下载MyBatis的源码压缩包,解压之后,通过idea打开这个maven项目,可以使用maven插件compile编译,开始会爆出error,把项目中的license.txt文件删除即可。

导入MySQL驱动依赖

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version>
</dependency>

测试程序是否能运行

public class Test01 {public static void main(String[] args) throws IOException {InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();UserMapper mapper = sqlSession.getMapper(UserMapper.class);List<User> userList = mapper.getUserList();for (User user : userList){System.out.println(user);}}
}

此时对应要创建mapper.xml文件和对应的Mapper接口,并且通过mybatis-config.xml文件绑定。
MyBatis通过四步完成了JDBC的封装。可以从这四个方面切入分析MyBatis源码。

1.获取文件输入流

Resources.getResourceAsStream(“mybatis-config.xml”);

//最终底层调用的是ClassLoaderWrapper对象的,使用加载器对象中的类加载器来获得输入流。
ClassLoader[] getClassLoaders(ClassLoader classLoader) {return new ClassLoader[]{classLoader,//传递的参数为nulldefaultClassLoader,//默认没有赋值nullThread.currentThread().getContextClassLoader(),//通过当前线程获取类加载器对象getClass().getClassLoader(),//通过当前类获取加载器对象systemClassLoader};//初始化ClassLoaderWrapper对象赋值ClassLoader.getSystemClassLoader();
}
//最终是通过ClassLoader对象调用getResourceAsStream方法获取的输入流
InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {for (ClassLoader cl : classLoader) {if (null != cl) {InputStream returnValue = cl.getResourceAsStream(resource);if (null == returnValue) {returnValue = cl.getResourceAsStream("/" + resource);}if (null != returnValue) {return returnValue;}}}return null;
}

2.构建DefaultSqlSessionFactory对象

new SqlSessionFactoryBuilder().build(inputStream);

//enviroment为null,properties为null
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);//在XMLConfigBuilderreturn build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {if (inputStream != null) {inputStream.close();}} catch (IOException e) {// Intentionally ignore. Prefer previous error.}}
}
//创建XMLConfigBuilder对象之前调用重载的构造方法先创建XMLMapperEntityResolver对象,此时的enviroment和props还是为null
//XMLMapperEntiryRresolver对象是为了识别mybatis-config.xml以及mapper.xml文件里面的内容
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
//再创建XPathParser,依次参数inputStream,true,null,entityResolver
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {commonConstructor(validation, variables, entityResolver);//给XPathParser对象属性赋值//validation,entityResolver,variables为null,xpath//http://java.sun.com/jaxp/xpath/dom,xpath传教用到的urithis.document = createDocument(new InputSource(inputStream));//给document对象赋值,
}
1、commonConstructor方法给XPathParser属性赋值;
//XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
//通过debug发现,会先进入InstrumentationImpl类,再将XPahtFactoryFinder先进行类加载,初始化类里面的静态变量,然后再进行new对象执行,在执行下面方法过程中,会读取java.home/lib/jaxp.properties路径下是否有这个文件。最终通过反射创建的XPathFactoryImpl实例。
XPathFactory f = _newFactory(uri);//底层最终用到的是反射创建对象
assert xpathFactory == null;//使用到了没有用到的修饰符,断言,如果xpathFactory不为null就抛出异常
xPathFactory = (XPathFactory) clazz.newInstance();
//最终通过反射创建XPathFactory类型的对象,实际创建的是XPathFactoryImpl对象
Xpath xpath = new XpathImpl(null,null,false,true,new FeatureManager());2、createDocument(new InputSource(inputStream))给XPathParser的document属性赋值Document类型;
//factory = DocumentBuilderFactory.newInstance();最终通过是DocumentBuilderFactory.class.newInstance()构造实例
//上面实例中的属性:Map<String, Object> attributes,Map<String, Boolean> features均为null。
//1.factory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing",true);features=new HashMap;
往features的String,Boolean集合中添加了一个键值对;
//2.factory.setValidating(validation)给DocumentBuilderFactory属性validation赋值true;原来是false
//3.factory.setNamespaceAware(false);给DocumentBuilderFactory属性namespaceAware赋值false;原来是false;
//4.factory.setIgnoringComments(true);给DocumentBuilderFactory属性namespaceAware赋值ignoreComments赋值true;f
//5.factory.setIgnoringElementContentWhitespace(false);DocumentBuilderFactory属性whitespace赋值false;false
//6.factory.setCoalescing(false);DocumentBuilderFactory属性coalescing赋值false;原来值为false
//7.factory.setExpandEntityReferences(true);DocumentBuilderFactory属性expandEntityRef属性为true;原来值f
validating验证;namespaceAware命名空间感知;whitespace空白;expandEntityRef展开实体引用;ignoreComments忽略注释;coalescing凝聚;上面的set开头的方法完成factory实例属性的部分初始化;
//DocumentBuilder builder= factory.newDocumentBuilder();new DocumentBuilderImpl(factory,null,features,true);DocumentBuilderImpl构造方法执行domParser = new DOMParser();//无参构造调用this(null,null),调用super(new XIncludeAwareParserConfiguration())给父类XMLParser的属性fConfiguration赋值,并且初始化部分参数。fConfiguration = new XIncludeAwareParserConfiguration();
DOMParser extends AbstractDOMParser extends AbstractXMLDocumentParser extends XMLParser;XIncludeAwareParserConfiguration实例初始化;new XIncludeAwareParserConfiguration()调用this(null,null,null)调用super(null,null,null)再调用super(null);
ParserConfigurationSettings(null){Set<String> fRecognizedFeatures = new HashSet<String>();Set<String> fRecognizedProperties = new HashSet<String>();Map<String, Boolean> fFeatures = new HashMap<String, Boolean>();Map<String, Object> fProperties = new HashMap<String, Object>();XMLComponentManager fParentSettings = null;Map<String,Boolean> fFeatures = new HashMap();//由XML11Configuration再次赋值Map<String, Object> fProperties = = new HashMap();//由XML11Configuration再次赋值
}XML11Configuration(null,null,null){ArrayList fComponents = new ArrayList();ArrayList fXML11Components = new ArrayList();ArrayList fCommonComponents = new ArrayList();Map<String, Object> fProperties = = new HashMap();//fEntityManager实例处理XMLEntityManager fEntityManager = new XMLEntityManager();//XMLEntityManager在实例化的过程中,也初始化了部分属性,用到的属性有XMLEntityScanner fEntityScanner = new XMLEntityScanner();String[] recognizedFeatures的数组元素添加至fRecognizedFeatures集合中;fFeatures集合中put进去键值对;String[] recognizedProperties;//fRecognizedProperties.addAll(Arrays.asList(数组));SymbolTable fSymbolTable = symbolTable == null ? new SymbolTable() : symbolTable;//fProperties.put("http://apache.org/xml/properties/internal/symbol-table", fSymbolTable);fProperties.put("http://apache.org/xml/properties/internal/entity-manager", fEntityManager);fCommonComponents.add(component);//componnet:fEntityManager、
//上面方法执行中从component中取的一些常量,如果这些至不在fRecognizedFeatures、fRecognizedProperties属性中,添加进去
//fFeatures、fProperties添加没有加入的元素,如果有添加进去一次,则fConfigUpdated改为true
//这两者中fFeatures不含ALLOW_JAVA_ENCODINGS T,WARN_ON_DUPLICATE_ENTITYDEF T,STANDARD_URI_CONFORMANT F
//fProperties不含BUFFER_SIZE=new Integer(DEFAULT_BUFFER_SIZE);//XMLErrorReporter实例处理XMLErrorReporter fErrorReporter = new XMLErrorReporter();//初始化属性Map<String, MessageFormatter> fMessageFormatters = new HashMap<>();//XMLLocator fLocator = fentityManager.entityScanner;get了属性fProperties.put("http://apache.org/xml/properties/internal/error-reporter", fErrorReporter);fCommonComponents.add(component);//component:fErrorReporter
//fErrorReporter获取的属性都有,许需要添加属性进去//XMLNSDocumentScannerImpl实例处理XMLNSDocumentScannerImpl fNamespaceScanner = new XMLNSDocumentScannerImpl();fProperties.put("http://apache.org/xml/properties/internal/document-scanner", fNamespaceScanner);addComponent((XMLComponent) fNamespaceScanner);
XMLNSDocumentScannerImpl extends XMLDocumentScannerImpl extends XMLDocumentFragmentScannerImpl extends XMLScanner
//fComponents.add(component);component:fNamespaceScanner;
//addRecognizedParamsAndSetDefaults(component);component:fNamespaceScanner;
//在XMLDocumentScannerImpl的数组RECOGNIZED_FEATURES和XMLDocumentFragmentScannerImpl中的数组RECOGNIZED_FEATURES进行了拼接。RECOGNIZED_PROPERTIES、RECOGNIZED_PROPERTIES数组拼接。//这里和上面唯一不同的是,下面使用了数组的拼接。
//如果fRecognizedFeatures、fRecognizedProperties不含数组中的元素,之间添加至各自的Set集合中。//1.先将对象put进去fProperties的<String,Object>的map集合中//2.fComponents的list集合有没有,没有add进去//3.fRecognizedFeatures和fRecognizedProperties的set集合有没有每个特点对象里面的常量,没有就add进去。//4.fFeatures<String,Boolean>和fProperties<String,Object>的map集合有没有这些元素,没有就add进去//往fProperites中put了两队键值对//fErrorReporter的map<String,MessageFormatter>中put了两队键值对//最后获取本地Locale,并且设置在XIncludeAwareParserConfiguration实例和fErrorReporter实例的locale属性。fConfigUpdated = false;
}
XIncludeAwareParserConfiguration(null,null,null){//前面往fComponents、fXML11Components、fXML11Components里面的对象都调用了设置属性的方法NamespaceSupport fNonXIncludeNSContext = new NamespaceSupport();NamespaceContext fCurrentNSContext = fNonXIncludeNSContext;setProperty(NAMESPACE_CONTEXT, fNonXIncludeNSContext);//最后会将键值对添加至fProperties.put(propertyId, value)中
}
到这里,XIncludeAwareParserConfiguration对象创建完毕;
XIncludeAwareParserConfiguration extends XML11Configuration extends ParserConfigurationSettings;DOMParser实例初始化;
XMLParser(new XIncludeAwareParserConfiguration()){fConfiguration = config;fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);
{http://apache.org/xml/properties/internal/entity-resolver,http://apache.org/xml/properties/internal/error-handler}
}
AbstractXMLDocumentParser(new XIncludeAwareParserConfiguration()){XMLDocumentHandler fDocumentHandler = new DOMParser();//XIncludeAwareParserConfiguration实例属性赋值XMLDTDHandler fDTDHandler = new DOMParser();XMLDTDContentModelHandler fDTDContentModelHandler = new DOMParser();
}
AbstractDOMParser(new XIncludeAwareParserConfiguration()){fConfiguration.addRecognizedFeatures (RECOGNIZED_FEATURES);String[] RECOGNIZED_FEATURES = {http://xml.org/sax/features/namespaces,http://apache.org/xml/features/dom/create-entity-ref-nodes,http://apache.org/xml/features/include-comments,http://apache.org/xml/features/create-cdata-nodes,http://apache.org/xml/features/dom/include-ignorable-whitespace,http://apache.org/xml/features/dom/defer-node-expansion};往fComponents、fXML11Components、fXML11Components对象里面的设置布尔值;fConfiguration.addRecognizedProperties (RECOGNIZED_PROPERTIES);String[] RECOGNIZED_PROPERTIES = {http://apache.org/xml/properties/dom/document-class-name,http://apache.org/xml/properties/dom/current-element-node};fConfiguration.setProperty (DOCUMENT_CLASS_NAME,DEFAULT_DOCUMENT_CLASS_NAME);//两个都是String类型//className,com.sun.org.apache.xerces.internal.dom.DocumentImpl
}
DOMParser(null,null){super(new XIncludeAwareParserConfiguration());fConfiguration.addRecognizedProperties(RECOGNIZED_PROPERTIES);fConfiguration.addRecognizedFeatures(RECOGNIZED_FEATURES);//还是往这个set集合里面添加没有的元素
}DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Map<String, Object> dbfAttrs,Map<String, Boolean> features, boolean secureProcessing);
DocumentBuilderImpl(this,null,features,true)//freatures现在只有一对键值对{http://javax.xml.XMLConstants/feature/secure-processing=true//1.先初始化了DOMParser实例ErrorHandler fInitErrorHandler = new DefaultValidationErrorHandler(domParser.getXMLParserConfiguration().getLocale());Locale.getDefault();//获取的Locale和这个实例初始化一样都是获取Locale.getDefault()setErrorHandler(fInitErrorHandler);//最终是给fConfiguration中的三个对象集合中对应的对象设置属性domParser.setFeature(http://xml.org/sax/features/validation,true);domParser.setFeature(http://xml.org/sax/features/namespaces,true);domParser.setFeature(http://apache.org/xml/features/dom/include-ignorable-whitespace,true);domParser.setFeature(http://apache.org/xml/features/dom/create-entity-ref-nodes,false);domParser.setFeature(http://apache.org/xml/features/include-comments,false);domParser.setFeature(http://apache.org/xml/features/create-cdata-nodes,true);fSecurityPropertyMgr = new XMLSecurityPropertyManager();domParser.setProperty(http://www.oracle.org/xml/jaxp/properties/xmlSecurityPropertyManager, fSecurityPropertyMgr);//domParser属性securityPropertyManager赋值,然后三大对象集合中对象属性赋值,最终添加到fProperties<String,Object>map集合中。fSecurityManager = new XMLSecurityManager(secureProcessing);//true//domParser属性securityManager赋值domParser.setProperty(SECURITY_MANAGER, fSecurityManager);Schema grammar = null;fSchemaValidationManager = null;fUnparsedEntityHandler = null;fSchemaValidatorComponentManager = null;fSchemaValidator = null;setFeatures(features);//最终将键值对添加至fFeatures中setDocumentBuilderFactoryAttributes(dbfAttrs);//dbfAttrs = nullEntityResolver fInitEntityResolver = domParser.getEntityResolver();//fConfiguration中没有这个键值对
}
DocumentBuilderImpl实例初始化完成,在这个过程中,先完成XIncludeAwareParserConfiguration实例初始化,赋值给DOMParser的属性fConfiguration,再初始化完成DOMParser实例,再DocumentBuilderImpl构造方法中完成属性的赋值;builder.setEntityResolver(entityResolver);//new XMLMapperEntityResolver()
fConfiguration.setProperty(ENTITY_RESOLVER,new EntityResolverWrapper(entityResolver));
//http://apache.org/xml/properties/internal/entity-resolver=obj,put进fProperties<String,Object>集合。
builder.setErrorHandler(errorHandler);
//http://apache.org/xml/properties/internal/error-handler=obj。中从fConfiguration对象中拿ErrorHandlerWrapper实例,存在实例,给实例的属性ErrorHandler fErrorHandler赋值errorHandler,如果不存在,创建一个ErrorHandlerWrapper实例并且设置上面同样的属性。
domParser.parse(is);//new InputSource(inputStream),inputStream是mybatis配置文件流
//XMLInputSource xmlInputSource = new XMLInputSource(null,null,null);
//xmlInputSource.setByteStream(inputSource.getByteStream());inputStream
//xmlInputSource.setCharacterStream(inputSource.getCharacterStream());null
//xmlInputSource.setEncoding(inputSource.getEncoding());null
parse(xmlInputSource);new XMLInputSource(null,null,null);方法重载
//securityManager、securityPropertyManager属性都已经赋值,不为null。
fConfiguration.parse(inputSource);//XML11Configuration,用fParseInProgress标志控制
//setInputSource(source);source = new XMLInputSource(null,null,null);finputSource
parse(true);
//fValidationManager.reset();将ValidationManager对象的Vector集合执行removeAllElements(),两个属性赋值false
//fVersionDetector.reset(this);将fConfiguration对象的fSymbolTable、fErrorReporter、fEntityManager从map集合中取出来赋值给XMLVersionDetector的三个对应属性,也是属性初始化过程。
//configurePipeline();初始化fCurrentScanner实例,XMLDocumentScannerImpl
//resetCommon();将fCommonComponents集合里面的对象调用reset(XMLComponentManager componentManager)
short version = fVersionDetector.determineDocVersion(fInputSource);//version = 1;
//xml流read()前四次{60,63,120,109},Object[] encodingDesc = new Object{"UTF-8",null}
//RewindableInputStream实例的reset方法,UTF8Reader reader
//fCurrentEntity对象初始化,
fInputSource = null;//最终属性赋值为null
Document doc = domParser.getDocument();
//发现直接是从domParser实例的父类属性中fDocument中get值,这个值初始化只能的父类的startDocument方法,查找对象创建过程中哪里调用了这个方法。经过之前的总结发现是在XML11Configuration startDocumentParsing中初始化了document对象,查找到发现不对。通过debug测试看能否找到调用fDocument方法,通过debug发现就是configuration对象调用parse(true)方法fVersionDetector.startDocumentParsing((XMLEntityHandler) fCurrentScanner, version)时完成了document对象的初始化。
domParser.dropDocumentReferences();
//将里面的属性赋值为null
代码到这里标志XPathParser对象创建完毕,开始创建XMLConfigBuilder对象。parser是XMLConfigBuilder实例
parser.parse();
Configuration parse(){parseConfiguration(parser.evalNode("/configuration"));return configuration;
}
//Configuration对象的属性parser是XPathParser类型
XPathParser{XNode evalNode(String expression);//调用evalNode(document,var1)XNode evalNode(Object root,String expression);Object evalNode(var2,var1,QName);//调用XPathImpl xpath的evalNode方法
}
XPathImpl{Object evalNode(String expression,Object item,QName returnType);XObject eval(expression,item);
}通过debug获取的截取获取的evaluate(String expression, Object root, QName returnType)返回值为null;
关键代码{XPathImp{XObject resultObject = eval(expression, item);"/configuration",DeferredDocumentImpl对象;com.sun.org.apache.xpath.internal.XPath xpath = new XPath(expression,null,prefixResolver,0);
//m_funcTable = new FunctionTable();初始化了m_funcTable的Class数组和map集合
//errorListener = new com.sun.org.apache.xml.internal.utils.DefaultErrorHandler();
//m_pw = new PrintWriter(System.err, true);
//m_patternString = expression;
//new com.sun.org.apache.xpath.internal.compiler.XPathParser(errorListener,null);
//Compiler compiler = new Compiler(errorListener, locator, m_funcTable);
//Expression expr = WalkingIteratorxpathSupport = new com.sun.org.apache.xpath.internal.XPathContext();NodeIterator ni = new com.sun.org.apache.xml.internal.dtm.ref.DTMNodeIterator(XNodeSet)}XPath{xobj = m_mainExp.execute(xctxt);//m_mainExp = WalkingIterator//XNodeSet iter = new XNodeSet((LocPathIterator)m_clones.getInstance());getInstance就是m_mainExp//iter.setRoot(xctxt.getCurrentNode(), xctxt);//XNodeSet 中属性DTMIterator m_iter m_mainExp}
}
只要debug进入XPathImpl的ni.nextNode()的方法,返回结果为null。只能跳过handle取值过程。
DTMNodeIterator{public Node nextNode() throws DOMException{if(!valid)throw new DTMDOMException(DOMException.INVALID_STATE_ERR);int handle=dtm_iter.nextNode();//dtm_iter XNodeSet,这里的handle肯定不是-1if (handle==DTM.NULL)return null;return dtm_iter.getDTM(handle).getNode(handle);}
}//XIncludeAwareParserConfiguration
//XML11Configuration startDocumentParsing((XMLEntityHandler) fCurrentScanner, version);初始化document对象
//XMLDTDValidator实现XMLDocumentHandler
//XPathParser中的document实际是new DeferredDocumentImpl(false)的父类实现了Document接口,接口继承Node接口,在初始化document对象时,都向上super调用了父抽象类的构造方法。
DeferredDocumentImpl extends DocumentImpl extends CoreDocumentImpl extends ParentNode extendss ChildNode extends NodeImpl implents Document
//WalkingIterator extends LocPathIterator
//1.new DeferredDocumentImpl(false);super(false) => new DocumentImpl(false);super(false)
//2.new CoreDocumentImpl(false);super(null) => protected ParentNode(CoreDocumentImpl ownerDocument);super(null);this.ownerDocument = null;CoreDocumentImpl ownerDocument属性在PatentNode抽象类中
//3.protected ChildNode(CoreDocumentImpl ownerDocument);super(null) => protected NodeImpl(CoreDocumentImpl ownerDocument)NodeImpl ownerNode = null;
//在初始化ParentNode抽象类CoreDocumentImpl类型ownerDocument时,赋值为空,而后在子类CoreDocumentImpl构造方法中赋值为this。
//XNode中的Node node是DeferredElementImpl实例对象
//DeferredElementImpl只有一个构造方法,参数DeferredDocumentImpl ownerDoc, int nodeIndex,ownerDoc应该传入了初始化的DeferredDocumentImpl实例,nodeIndex环境的是4。构造方法执行的类
DeferredElementImpl extends ElementImpl extends ParentNode extends ChildNode>NodeImpl在创建Environment对象时,使用了一种方式,通过先创建Environment的静态内部类Builder,这个内部类的属性和外部类属性完全相同,通过先对这个对象赋值,再通过内部类对象的方法创建外部类的对象。最终将environment对象注入到config中//BeanWrapper implements ObjectWrapper
//Reflector setMethods属性JDBC=JdbcTransactionFactory.class
MANAGED=ManagedTransactionFactoryJNDI=JndiDataSourceFactory
POOLED=PooledDataSourceFactory PooledDataSourceFactoty继承了UnpooledDataSourceFactor
UNPOOLED=UnpooledDataSourceFactory
//UnpooledDataSourceFactory拥有PooledDataSource数据源属性
//最终传教SqlSessionFactory接口实现类的对象
public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);
}
mybatis绑定mapper可以通过源码得知package优先级最高,其次是resource或者url或者class

通过SqlSessionFactoryBuilder对象传入的输入流,将解析的xml文件信息放置在Configuration对象中,解析xml文件使用到类,时jdk自带的类,mybatis的类通过封装创建这些类的实例,来调用这些实例的方法完成xml的解析,直接将解析好的Configuration对象调用SqlSessionFactoryBuilder构造方法。

3.创建DefaultSqlSession实例

sqlSessionFactory.openSession()

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;try {//获取environment对象的属性TransactionFactory、DataSource,数据源初始化在创建完成时就完成初始化了。//transactionManager type="JDBC"=JdbcTransactionFactory.class//dataSource type="POOLED"=PooledDataSourceFactory.class,dataSource时PooledDataSourceFactory的属性final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);//JdbcTransaction实例创建tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);//Executor执行器实例创建,默认SimpleExecutorfinal Executor executor = configuration.newExecutor(tx, execType);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();}
}

将configuration、executor、autoCommit三个属性赋值给DefaultSqlSession对象。

4.获取Mapper接口实例

sqlSession.getMapper(UserMapper.class)

sqlSession.getMapper(UserMapper.class);//这里采用了jdk的动态代理模式
动态代理使用到的类MapperRegistry、MapperProxy、MapperProxyFactory
//通过MapperRegistry存储配置文件接口信息,Class<?>, MapperProxyFactory<?>的key,valuemap集合,调用MapperProxyFactory<T>对象的newInstance方法动态代理创建接口对象,在这里是MapperProxy实现InvocationHandler接口,重写了invoke方法。
1.invoke(Object proxy,Method method,Object[] args);
2.cacheInvoker(method).invoke(proxy,method,args,sqlSession);
//MapperMethodInvoker cacheInvoker(Method method)该方法执行过程中,正常情况下Map<Method, MapperMethodInvoker> methodCache集合中会put进去method=MapperProxy.PlainMethodInvoker一对键值对,对象中的属性mapperMethod会有另外两个静态内部类:SQLCommand,MethodSignature
3.mapperMethod.execute(sqlSession, args);
SqlCommandType{UNKNOWN,INSERT,UPDATE,DELETE,SELECT,FLUSH}4.最终通过动态代理,底层最终调用的还是sqlSession对象也就是DefaultSqlSession对象实例。
public <E> List<E> selectList(String statement, Object parameter){};
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds){};
5.使用到JDBC4Connection.prepareStatement(sql)。ResultSetWrapperrang结果集处理

源码可用点

java.io.File.separator;//等价于"\\"
new Properties().load(new FileInputStream(new File(path)));//将properties文件以流的方式读取成Properties实例
assert file == null;//如果file属性不为null,程序出错
Class.forName(className,false,classLoader);//不进行类加载获取Class类,className要带全路径名
clazz.cast(obj);将obj实例类型转换为clazz类型,能转换正常执行,不能则抛出异常;
type instanceof TypeVariable;//不知道这个是什么类型才这样
type instanceof ParameterizedType;//type List<?>,Map<String,Object>
type instanceof GenericArrayType;//type Map<?,?>[],map数组list数组
//类型基本上都是Parameterized
clazz1.isAssignableFrom(clazz2);//clazz2是clazz1的子类或者本身返回true

MyBatis源码简单分析相关推荐

  1. Hessian 源码简单分析

    Hessian 源码简单分析 Hessian 是一个rpc框架, 我们需要先写一个服务端, 然后在客户端远程的调用它即可. 服务端: 服务端通常和spring 做集成. 首先写一个接口: public ...

  2. poco源码简单分析

    自动化工具poco源码简单分析 Airtest简介 Airtest是网易游戏开源的一款UI自动化测试项目,目前处于公开测试阶段,该项目分为AirtestIDE.Airtest.Poco.Testlab ...

  3. FFmpeg的HEVC解码器源码简单分析:概述

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  4. FFmpeg的HEVC解码器源码简单分析:解码器主干部分

    ===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...

  5. JSP 编译和运行过程与JSP源码简单分析

    JSP 编译和运行过程与JSP转移源码简单分析 Web容器处理JSP文件请求的执行过程主要包括以下4个部分: 1. 客户端发出Request请求 2. JSP Container 将JSP转译成Ser ...

  6. MyBatis源码骨架分析

    源码包分析 MyBatis 源码下载地址:https://github.com/MyBatis/MyBatis-3 MyBatis源码导入过程: 下载MyBatis的源码 检查maven的版本,必须是 ...

  7. 线程的3种实现方式并深入源码简单分析实现原理

    前言 本文介绍下线程的3种实现方式并深入源码简单的阐述下原理 三种实现方式 Thread Runnable Callable&Future 深入源码简单刨析 Thread Thread类实现了 ...

  8. reentrantlock失效了?_ReentrantLock 源码简单分析

    JAVA中锁的实现最常见的方式有两种,一种是 synchronized关键字,一种是Lock.实际的开发过程中,要对这两种方式进行取舍. synchronized是基于JVM层面实现的, Lock却是 ...

  9. ChaLearn Gesture Challenge_3:Approximated gradients源码简单分析

    前言 上一篇博文ChaLearn Gesture Challenge_2:examples体验 中简单介绍了CGC官网提供的丰富的sample,本节来简单分下其中的一个sample源码,该sample ...

最新文章

  1. Asp.net SignalR 实现服务端消息推送到Web端
  2. 乘法逆元总结 3种基本方法
  3. Elasticsearch中的Multi Match Query
  4. 在线普通话转粤语发音_香港最新悬疑侦探剧福尔摩师奶,粤语知识好难
  5. uboot烧录到SD卡
  6. centos 需要哪些常用端口_仓库加盟:电商仓库需要配备哪些常用仓储设备
  7. 用纯css改变下拉列表select框的默认样式
  8. android 黑名单中电话拦截
  9. matlab2017a安装出现license checkout failed Error-8
  10. 一二线城市知名IT互联网公司名单!
  11. 机器学习读书笔记: 概率图模型
  12. 联合查询(多表查询)
  13. Java调用WebService接口实现发送手机短信验证码功能,java 手机验证码,WebService接口调用
  14. [转]验证码识别技术
  15. kubernetes device or resource busy的问题
  16. HearthBuddy炉石兄弟 格雷迈恩
  17. 连接局域网内的Mysql8服务器
  18. SDN南向接口和北向接口区别
  19. 微信公众号开发,移动端开发遇到的问题及其他技巧
  20. Asp.net 路由详解

热门文章

  1. 折半查找判定树 二叉排序树 查找成功平均查找长度 查找失败平均查找长度
  2. 如何生成tfrecord
  3. 农村商业银行服务器未收到证书,不及时更新“证书” 当心网银U盾失效
  4. DiskMan使用方法
  5. Excel保护怎么解除保护
  6. mysql中的表自增的id太大了,可以重新设置自增起始值
  7. 探寻软件的永恒之道 ——评介《建筑的永恒之道》 - 撰文/透明
  8. SourceTree安装跳过注册
  9. html.append清空,关于jquery的append()和html()使用
  10. 地图上如何量方位角_地图投影怎么做到按条件(等角、等面积、等距)投影的?...