日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Mybatis 源码探究 (3)创建 SqlSessionFactory对象 执行sqlSession.getMapper()方法

發布時間:2025/3/19 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mybatis 源码探究 (3)创建 SqlSessionFactory对象 执行sqlSession.getMapper()方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Mybatis 源碼探究 (3)創建 SqlSessionFactory對象

時隔許久,終于又能接著來搞他啦。Mybatis 一起來探究吧。

先笑會再進入主題吧

開始啦

一、new SqlSessionFactoryBuilder().build(inputStream) 方法

String resource="mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream); public SqlSessionFactory build(InputStream inputStream) {//在這里又接著調用了重載方法build 我們接著往下走啊 return build(inputStream, null, null); }

二、SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) 方法

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {//XMLConfigBuilder是對mybatis的配置文件進行解析的類,會對myabtis解析后的信息存放在Configuration對象中XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);// 下面這句到重點啦return build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {inputStream.close();} catch (IOException e) {// Intentionally ignore. Prefer previous error.}} }

一個一個講啊,慢慢來。

1、 new XMLConfigBuilder(inputStream, environment, properties);

XMLConfigBuilder : 翻譯過來就是XML配置器

XMLConfigBuilder是對mybatis的配置文件進行解析的類,會對myabtis解析后的信息存放在Configuration對象中,Configuration對象

會貫穿整個mybatis的執行流程,為mybatis的執行過程提供各種需要的配置信息。

public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props); }

XPathParser 和 XMLMapperEntityResolver 不是主要研究對象,我放在了文章最后,好奇的話,可以先滑到文末去看。

三、build(parser.parse()) 方法

先看parser.parse()方法 它的返回對象是核心配置對象Configuration

public Configuration parse() {if (parsed) {throw new BuilderException("Each XMLConfigBuilder can only be used once.");}parsed = true;parseConfiguration(parser.evalNode("/configuration"));return configuration; }

進入到parseConfiguration(parser.evalNode("/configuration"))方法

可以看到 在這里就是將我們配置的好的文件 一步一步解析封裝到Configuration對象去。

private void parseConfiguration(XNode root) {try {// issue #117 read properties firstpropertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);loadCustomLogImpl(settings);typeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));reflectorFactoryElement(root.evalNode("reflectorFactory"));settingsElement(settings);// read it after objectFactory and objectWrapperFactory issue #631environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));mapperElement(root.evalNode("mappers"));} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}}

這一段代碼主要作用就是將所有的配置文件加載到給定的對象。

我對于研究這個非常不熟練,結果就是走不出來。

mapperElement(root.evalNode("mappers"))里面要研究的東西不少,先略過哈。

四、return build(parser.parse()); 回到我們的入口處

我們可以知道 parser.parse() 構建出了一個 Configuration 對象,并成為了build()方法的入參。

這個build(parser.parse()); 是

public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}

這個地方就是將之前已經賦值好的Configuration 放在里面

public DefaultSqlSessionFactory(Configuration configuration) {this.configuration = configuration;}

課間休息

地點:長沙

五、SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

至此 我們獲得了 SqlSessionFactory 對象,我們可以通過這獲取到mybatis操作數據庫的 SqlSession 對象。

SqlSession sqlSession = sessionFactory.openSession();

openSession() 是SqlSessionFactory 接口下的方法

public interface SqlSessionFactory {SqlSession openSession();SqlSession openSession(boolean autoCommit);SqlSession openSession(Connection connection);SqlSession openSession(TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType);SqlSession openSession(ExecutorType execType, boolean autoCommit);SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType, Connection connection);Configuration getConfiguration(); }

我們這里調用的方法是這個哈

@Overridepublic SqlSession openSession() {// openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}

最后一個參數就是是否提交,如果不為true,我們做了修改or刪除,數據庫并不會修改or刪除。

接著往下看:

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);final 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();}}

最后返回mybatis操作數據庫的 SqlSession 對象。

六、MyUserMapper mapper = sqlSession.getMapper(MyUserMapper.class);

/**檢索映射器。參數:type – 映射器接口類類型參數:<T> – 映射器類型返回:綁定到此 SqlSession 的映射器*/<T> T getMapper(Class<T> type);

接下來開始套娃哈

我們實際調用的是它的實現類里的方法:

@Override public <T> T getMapper(Class<T> type) {return configuration.getMapper(type, this); }

你看又牽扯到configuration對象了哈,知道它多重要了吧。

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {return mapperRegistry.getMapper(type, sqlSession); }

到了mapperRegistry 這個對象拉。 mapperRegistry的翻譯就是映射器注冊表 這個地方我目前還沒有搞懂它是什么時候注冊進去的哈。

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {// 這里是去獲得 我們傳過來的 MyUserMapper.class的代理類的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);}}

接下來繼續看這個 mapperProxyFactory.newInstance(sqlSession) 方法

public T newInstance(SqlSession sqlSession) {final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);return newInstance(mapperProxy);}

接著套丫

protected T newInstance(MapperProxy<T> mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}

當我們看到這里的時候就知道mybatis是通過反射和代理來進行這些操作的哈。

真實執行對象并不在,而是在 MapperProxy mapperProxy Mapper的代理對象中。

那個具體執行的,等下一篇博客哈。我還有很多沒懂的。

七、XPathParser

public class XPathParser {private final Document document;private boolean validation;private EntityResolver entityResolver;private Properties variables;private XPath xpath; }
  • Document(Document對象)

    Document 對象代表整個 XML 文檔,是一棵文檔樹的根,可為我們提供對文檔數據的最初(或最頂層)的訪問入口。

  • validation(是否開啟驗證標記)

    該標記表示設置解析器在解析文檔的時候是否校驗文檔,在創建DocumentBuilderFactory實例對象時進行設置。

  • EntityResolver (加載本地的DTD文件

    如果解析mybatis-config.xml 配置文件,默認聯網加載http://mybatis.org/dtd/mybatis-3- config.dtd 這個DTD 文檔,當網絡比較慢時會導致驗證過程緩慢。在實踐中往往會提前設置EntityResolver 接口對象加載本地的DTD 文件,從而避免聯網加載DTD文件。

  • XPath (XPath對象)

    XPath 是一種為查詢XML 文檔而設計的語言,它可以與DOM 解析方式配合使用,實現對XML 文檔的解析。

  • variables(配置參數集合)。

    對應配置文件中節點下定義的鍵值對集合,包括通過url或者resource讀取的鍵值對集合。

八、XMLMapperEntityResolver

對這個我沒有深究。doc注釋就是這么一句話:MyBatis DTD 的離線實體解析器 說實話DTD都是我第一次見 🤦?

當然百度是強大的。

它是EntityResolver子類,xml 的解析會基于事件觸發對應的 Resolver 或 Handler,當解析到 dtd 等外部資源時會

EntityResolver的resolveEntity方法。在XMLMapperEntityResolver.resolveEntity中,當解析到 mybatis-3-config.dtd、

mybatis-3-mapper.dtd 等資源時,會直接從 classpath 下的 org/apache/ibatis/builder/xml/ 路徑獲取資源,而不需要通過 url 獲取。

九、XMLMapperBuilder類

涉及到的類包括:

MapperBuilderAssistant:Mapper文件解析輔助類,包括了解析各種節點的方法。

BaseBuilder:XMLMapperBuilder與MapperBuilderAssistant的父類,保存了Configuration、TypeAliasRegistry、TypeHandlerRegistry三個屬性。

TypeAliasRegistry:別名對應關系,保存了字符串與類的對應信息,例如“String”字符串對應 String.class

TypeHandlerRegistry:注冊java.lang與java.sql類型對應關系

Configuration:Mapper文件解析節點完成后,存儲解析后的屬性信息。

XMLStatementBuilder:解析SQL語句節點類,解析后存儲在Configuration下的mappedStatements屬性

XMLMapperBuilder用于解析Mapper文件,包括namespace、parameterMap、resultMap以及各種SQL(insert/uppdate/delete/select)

解析過程中主要是parse()方法,

解析Mapper文件后會存儲在MapperBuilderAssistant以及它父類BaseBuilder的實例下,主要是Configuration類

自言自語

我這算是自己的閱讀筆記哈,無聊讀著看看。

算是我第一次讀源碼的記錄。

大家一起加油哦。

總結

以上是生活随笔為你收集整理的Mybatis 源码探究 (3)创建 SqlSessionFactory对象 执行sqlSession.getMapper()方法的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。