最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring整合Mybatis框架方法剖析

 更新時(shí)間:2023年07月13日 14:02:53   作者:王偵  
這篇文章主要為大家介紹了Spring整合Mybatis框架方法剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Spring整合其他框架的核心思路

就是將其他框架生成的類放到Spring容器中。同理,Spring整合Mybatis也是讓Mybatis生成的Mapper接口的代理對(duì)象作為Bean注冊到Spring容器中。

解決的核心問題

  • 1)通過FactoryBean創(chuàng)建Mapper接口代理對(duì)象,并且指定構(gòu)造方法參數(shù)為Mapper接口class,并且設(shè)置BeanDefinition.setAutowireMode(AUTOWIRE_BY_TYPE)。
  • 2)通過ImportBeanDefinitionRegistrar或者BeanDefinitionRegistryPostProcessor中創(chuàng)建的掃描器實(shí)現(xiàn)對(duì)多個(gè)Mapper接口代理對(duì)象的創(chuàng)建和注冊。
  • 3)掃描器篩選類時(shí)要重寫isCandidateComponent(),第一個(gè)isCandidateComponent()總是返回true(因?yàn)樘砑右粋€(gè)TypeFilter,其match方法總是返回true。),第二個(gè)isCandidateComponent()如果為接口時(shí)返回true。

ClassPathMapperScanner#registerFilters這里面添加一個(gè)總是返回true的TypeFilter:

    if (acceptAllInterfaces) {
      // default include filter that accepts all classes
      addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
    }

關(guān)于Mapper接口生成對(duì)象

  • 1.必須是一個(gè)對(duì)象(代理對(duì)象,JDK動(dòng)態(tài)代理Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy))
  • 2.這個(gè)對(duì)象必須實(shí)現(xiàn)Mapper接口(動(dòng)態(tài)代理對(duì)象必然實(shí)現(xiàn)Mapper接口)
  • 這兩條由mybatis保證
  • 3.必須在spring容器當(dāng)中

這條由mybatis-spring保證

1)FactoryBean,采用的就是這種方式,控制對(duì)象的生成過程,生成JDK動(dòng)態(tài)代理對(duì)象

2)ac.getBeanFactory().registerSingleton(),也是一樣麻煩

3)@Bean 方式,針對(duì)每一個(gè)接口都要一個(gè)@Bean,太麻煩

4)@Service 這樣是把類交給Spring,然后創(chuàng)建對(duì)象,但是這里是接口,創(chuàng)建對(duì)象會(huì)報(bào)錯(cuò),我們這里需要控制對(duì)象的生成過程(生成動(dòng)態(tài)代理)

Mybatis-Spring 1.3.2版本底層源碼執(zhí)行流程

  • 1)通過@MapperScan導(dǎo)入了MapperScannerRegistrar類
  • 2)MapperScannerRegistrar類實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口,所以Spring在啟動(dòng)時(shí)會(huì)調(diào)用MapperScannerRegistrar類中的registerBeanDefinitions方法
  • 3)在registerBeanDefinitions方法中定義了一個(gè)ClassPathMapperScanner對(duì)象,用來掃描mapper
  • 4)設(shè)置ClassPathMapperScanner對(duì)象(繼承自ClassPathBeanDefinitionScanner)可以掃描到接口,因?yàn)樵赟pring中是不會(huì)掃描接口的
  • 5)同時(shí)因?yàn)镃lassPathMapperScanner中重寫了isCandidateComponent方法,導(dǎo)致isCandidateComponent只會(huì)認(rèn)為接口是備選者Component
  • 6)通過利用Spring的掃描后,會(huì)把接口掃描出來并且得到對(duì)應(yīng)的BeanDefinition
  • 7)接下來把掃描得到的BeanDefinition進(jìn)行修改,把BeanClass修改為MapperFactoryBean,把AutowireMode修改為byType
  • 8)掃描完成后,Spring就會(huì)基于BeanDefinition去創(chuàng)建Bean了,相當(dāng)于每個(gè)Mapper對(duì)應(yīng)一個(gè)FactoryBean
  • 9)在MapperFactoryBean中的getObject方法中,調(diào)用了getSqlSession()去得到一個(gè)sqlSession對(duì)象,然后根據(jù)對(duì)應(yīng)的Mapper接口生成一個(gè)Mapper接口代理對(duì)象,這個(gè)代理對(duì)象就成為Spring容器中的Bean
  • 10)sqlSession對(duì)象是Mybatis中的,一個(gè)sqlSession對(duì)象需要SqlSessionFactory來產(chǎn)生
  • 11)MapperFactoryBean的AutowireMode為byType,所以Spring會(huì)自動(dòng)調(diào)用set方法,有兩個(gè)set方法,一個(gè)setSqlSessionFactory,一個(gè)setSqlSessionTemplate,而這兩個(gè)方法執(zhí)行的前提是根據(jù)方法參數(shù)類型能找到對(duì)應(yīng)的bean,所以Spring容器中要存在SqlSessionFactory類型的bean或者SqlSessionTemplate類型的bean。
  • 12)如果你定義的是一個(gè)SqlSessionFactory類型的bean,那么最終也會(huì)被包裝為一個(gè)SqlSessionTemplate對(duì)象,并且賦值給sqlSession屬性
  • 13)而在SqlSessionTemplate類中就存在一個(gè)getMapper方法,這個(gè)方法中就產(chǎn)生一個(gè)Mapper接口代理對(duì)象
  • 14)到時(shí)候,當(dāng)執(zhí)行該代理對(duì)象的某個(gè)方法時(shí),就會(huì)進(jìn)入到Mybatis框架的底層執(zhí)行流程

這里注意:SpringManagedTransaction是由SqlSessionFactoryBean引入的。

分析一下Mapper代理對(duì)象執(zhí)行查詢,比如userMapper.selectById(),其底層調(diào)用的是啥?

  • 其實(shí)調(diào)用的是SqlSessionTemplate.selectOne,主要是為了線程安全的,則每個(gè)線程都會(huì)獲取不同的DefaultSqlSession;如果是事務(wù),同一個(gè)線程會(huì)通過ThreadLocal存儲(chǔ)獲取同一個(gè)DefaultSqlSession(如果不是事務(wù),同一個(gè)線程執(zhí)行不同的sql語句也會(huì)獲取不同的DefaultSqlSession,這樣會(huì)導(dǎo)致一級(jí)緩存失效。一級(jí)緩存生效的前提是:同一個(gè)DefaultSqlSession執(zhí)行多個(gè)相同的sql語句)
  • SqlSessionTemplate會(huì)調(diào)用到SqlSessionProxy.selectOne,SqlSessionProxy的InvocationHandler是SqlSessionInterceptor,在SqlSessionInterceptor#invoke()里面會(huì)getSqlSession()返回一個(gè)SqlSession(這里返回的就是DefaultSqlSession)
  • SqlSessionProxy會(huì)調(diào)用至DefaultSqlSession.selectOne 線程不安全的

一級(jí)緩存失效問題:

  • 一般不使用一級(jí)緩存,跟事務(wù)隔離級(jí)別會(huì)沖突。比如讀已提交想要讀取到不同結(jié)果,但是使用緩存后,讀取到的每次都一樣。

Mybatis-Spring 2.0.6版本底層源碼執(zhí)行流程

核心區(qū)別:Mybatis-Spring 1.3.2在MapperScannerRegistrar#registerBeanDefinitions就會(huì)去掃描Mapper接口并生成BD注冊到Sprign容器。而Mybatis-Spring 2.0.6在MapperScannerRegistrar#registerBeanDefinitions只是注冊了一個(gè)新的BD:MapperScannerConfigurer,掃描邏輯放到了這個(gè)類中,因?yàn)檫@個(gè)類是一個(gè)BeanDefinitionRegistryPostProcessor。

  • 1)通過@MapperScan導(dǎo)入了MapperScannerRegistrar類
  • 2)MapperScannerRegistrar類實(shí)現(xiàn)了ImportBeanDefinitionRegistrar接口,所以Spring在啟動(dòng)時(shí)會(huì)調(diào)用MapperScannerRegistrar類中的registerBeanDefinitions方法
  • 3)在registerBeanDefinitions方法中注冊一個(gè)MapperScannerConfigurer類型的BeanDefinition
  • 4)而MapperScannerConfigurer實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor接口,所以Spring在啟動(dòng)過程中時(shí)會(huì)調(diào)用它的postProcessBeanDefinitionRegistry()方法
  • 5)在postProcessBeanDefinitionRegistry方法中會(huì)生成一個(gè)ClassPathMapperScanner對(duì)象,然后進(jìn)行掃描
  • 6)后續(xù)的邏輯和1.3.2版本一樣。

invokeBeanFactoryPostProcessors()中整合Mybatis的地方

invokeBeanFactoryPostProcessors()執(zhí)行流程:

  • 1)執(zhí)行通過ApplicationContext手動(dòng)添加進(jìn)來的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法
  • 2)執(zhí)行BeanFactory中實(shí)現(xiàn)了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法。這里會(huì)將ConfigurationClassPostProcessor的BeanDefinition實(shí)例化出來,并進(jìn)行調(diào)用。這里會(huì)處理MapperScannerRegistrar,是個(gè)ImportBeanDefinitionRegistrar。Mybatis-Spring 1.3.2直接在這里掃描,Mybatis-Spring 2.0.6新引入了一個(gè)BeanDefinitionRegistryPostProcessor:MapperScannerConfigurer。
  • 3)執(zhí)行BeanFactory中實(shí)現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法
  • 4)執(zhí)行BeanFactory中其他的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法(這里是個(gè)循環(huán),如果新注冊了BeanDefinitionRegistryPostProcessor,會(huì)繼續(xù)循環(huán)進(jìn)行處理)。Mybatis-Spring
    2.0.6的MapperScannerConfigurer會(huì)在這里掃描所有Mapper接口并生成BD注冊到Spring容器。
  • 5)執(zhí)行上面所有的BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法
  • 6)執(zhí)行通過ApplicationContext手動(dòng)添加進(jìn)來的BeanFactoryPostProcessor的postProcessBeanFactory()方法
  • 7)執(zhí)行BeanFactory中實(shí)現(xiàn)了PriorityOrdered接口的BeanFactoryPostProcessor的postProcessBeanFactory()方法
  • 8)執(zhí)行BeanFactory中實(shí)現(xiàn)了Ordered接口的BeanFactoryPostProcessor的postProcessBeanFactory()方法
  • 9)執(zhí)行BeanFactory中其他的BeanFactoryPostProcessor的postProcessBeanFactory()方法

以上就是Spring整合Mybatis框架源碼剖析的詳細(xì)內(nèi)容,更多關(guān)于Spring整合Mybatis的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java/Spring項(xiàng)目的包開頭為什么是com詳解

    Java/Spring項(xiàng)目的包開頭為什么是com詳解

    這篇文章主要介紹了Java/Spring項(xiàng)目的包開頭為什么是com的相關(guān)資料,在Java中包命名遵循域名反轉(zhuǎn)規(guī)則,即使用公司的域名反轉(zhuǎn)作為包的前綴,以確保其全球唯一性和避免命名沖突,這種規(guī)則有助于邏輯分層、代碼可讀性提升和標(biāo)識(shí)代碼來源,需要的朋友可以參考下
    2024-10-10
  • 使用FileReader采用的默認(rèn)編碼

    使用FileReader采用的默認(rèn)編碼

    這篇文章主要介紹了使用FileReader采用的默認(rèn)編碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 解決java使用axios.js的post請(qǐng)求后臺(tái)時(shí)無法接收到入?yún)⒌膯栴}

    解決java使用axios.js的post請(qǐng)求后臺(tái)時(shí)無法接收到入?yún)⒌膯栴}

    今天小編就為大家分享一篇解決java使用axios.js的post請(qǐng)求后臺(tái)時(shí)無法接收到入?yún)⒌膯栴},具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • Java邏輯運(yùn)算符之&&、||?與&、?|的區(qū)別及應(yīng)用

    Java邏輯運(yùn)算符之&&、||?與&、?|的區(qū)別及應(yīng)用

    這篇文章主要介紹了Java邏輯運(yùn)算符之&&、||?與&、?|的區(qū)別及應(yīng)用的相關(guān)資料,分別是&&、||?與&、?|,并探討了它們在不同應(yīng)用場景中的表現(xiàn)和優(yōu)化效果,需要的朋友可以參考下
    2025-03-03
  • SpringBoot靜態(tài)函數(shù)無法自動(dòng)注入Bean的原因分析與解決方案

    SpringBoot靜態(tài)函數(shù)無法自動(dòng)注入Bean的原因分析與解決方案

    在 Spring Boot 項(xiàng)目中,開發(fā)者常遇到一個(gè)典型問題:在靜態(tài)方法或靜態(tài)變量中嘗試使用 @Autowired 注入 Bean 時(shí),始終得到 null 值,本文將深入剖析這一問題的根源,并提供多種可靠解決方案,需要的朋友可以參考下
    2025-08-08
  • maven settings.xml文件的存放及配置(包含了配置阿里云鏡像)

    maven settings.xml文件的存放及配置(包含了配置阿里云鏡像)

    本文詳細(xì)解釋了Maven中settings.xml文件的存放位置,以及用戶級(jí)別和全局級(jí)別的區(qū)別,重點(diǎn)介紹了localRepository、交互模式、離線模式、插件組、代理設(shè)置、服務(wù)器認(rèn)證、鏡像列表和激活profiles的使用方法,感興趣的可以了解一下
    2025-09-09
  • mybatis中使用list作為參數(shù)方式

    mybatis中使用list作為參數(shù)方式

    在使用MyBatis時(shí),若要在Mapper XML中使用List作為參數(shù),并且collection屬性值類型為List,需要注意傳入的參數(shù)為List時(shí)不能使用lists!=null進(jìn)行判斷
    2026-01-01
  • Java實(shí)現(xiàn)word/pdf轉(zhuǎn)html并在線預(yù)覽

    Java實(shí)現(xiàn)word/pdf轉(zhuǎn)html并在線預(yù)覽

    這篇文章主要為大家詳細(xì)介紹了如何利用Java語言實(shí)現(xiàn)word、pdf文件轉(zhuǎn)html并在線預(yù)覽的功能,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-05-05
  • Java模擬登錄正方教務(wù)抓取成績、課表、空教室

    Java模擬登錄正方教務(wù)抓取成績、課表、空教室

    這篇文章主要介紹了Java模擬登錄正方教務(wù)抓取成績、課表、空教室等信息,Java實(shí)現(xiàn)模擬登錄正方教務(wù)抓取成績、課表、空教室,通過HttpClient來模擬瀏覽器請(qǐng)求,Jsoup解析網(wǎng)頁內(nèi)容,感興趣的小伙伴們可以參考一下
    2016-04-04
  • Spring Boot(四)之使用JWT和Spring Security保護(hù)REST API

    Spring Boot(四)之使用JWT和Spring Security保護(hù)REST API

    這篇文章主要介紹了Spring Boot(四)之使用JWT和Spring Security保護(hù)REST API的相關(guān)知識(shí),需要的朋友可以參考下
    2017-04-04

最新評(píng)論

舟山市| 铁岭县| 乌什县| 商水县| 奇台县| 龙岩市| 开化县| 湘潭市| 泰兴市| 莱阳市| 蕲春县| 南陵县| 遂宁市| 珲春市| 遂平县| 交城县| 托克逊县| 娱乐| 固原市| 禹城市| 赤壁市| 密云县| 贵阳市| 若尔盖县| 汝州市| 海安县| 丰县| 西乡县| 鄂托克前旗| 娄底市| 若尔盖县| 青州市| 巩留县| 通化县| 东方市| 铜山县| 建阳市| 洛阳市| 府谷县| 盐山县| 沂南县|