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

Spring整合Mybatis框架方法剖析

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

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

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

解決的核心問題

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

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

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

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

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

這條由mybatis-spring保證

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

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

3)@Bean 方式,針對每一個接口都要一個@Bean,太麻煩

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

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

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

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

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

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

一級緩存失效問題:

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

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

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

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

invokeBeanFactoryPostProcessors()中整合Mybatis的地方

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

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

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

相關(guān)文章

  • Java/Spring項目的包開頭為什么是com詳解

    Java/Spring項目的包開頭為什么是com詳解

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

    使用FileReader采用的默認編碼

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

    解決java使用axios.js的post請求后臺時無法接收到入?yún)⒌膯栴}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新評論

云安县| 鲁甸县| 葫芦岛市| 灌阳县| 揭西县| 韶山市| 阜宁县| 柳林县| 安宁市| 密山市| 邛崃市| 肇州县| 确山县| 高雄县| 滨州市| 洛隆县| 静安区| 蕲春县| 山阳县| 高阳县| 漳州市| 确山县| 凤冈县| 湟源县| 柏乡县| 武义县| 灵山县| 九龙坡区| 府谷县| 永嘉县| 华蓥市| 理塘县| 德钦县| 都江堰市| 贡山| 杭锦旗| 故城县| 大同市| 游戏| 军事| 镇康县|