成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Spring整合MyBatis之底層原理

原創 精選
數據庫 其他數據庫
使用起來是很簡單的,但是有沒有老鐵想過,為什么做了這么一個簡單的配置,這個Mapper就能操作數據庫了?

作者 | 波哥

審校 | 孫淑娟

如果老鐵們對Spring框架足夠熟悉,整合MyBatis其實很容易理解,當然這里假定老鐵們也已經熟悉了MyBatis框架。

在我們正常的應用開發過程中,使用MyBatis一般分為如下幾個步驟:

1.在配置類上增加MapperScan注解,例如:@MapperScan(basePackages = {"com.test.dao"},annotationClass = Mapper.class);

2.在basePackages指定的目錄下創建待MyBatis讀取的接口文件,例如:

@Mapper
public interface TestMapper {
......
}

3.在Service或者其他地方使用該Mapper來操作數據庫。

使用起來是很簡單的,但是有沒有老鐵想過,為什么做了這么一個簡單的配置,這個Mapper就能操作數據庫了?按理說這個Mapper是個接口,應該是不能被創建才對啊!如果你有這個疑問,證明你是個愛思考的好童鞋。

咱們直接進入主題。Spring要與MyBatis整合,簡單來說只要解決如下兩個問題:

一、Spring如何知道哪些類應該被管理?

要讓Spring去管理Bean的生命周期,首先需要對應的類被Spring掃描到,并且生成DeanDefinition,然后基于BeanDefinition生成Bean。下面對Spring生成BeanDefinition的方式做個小總結:

  • 包含Component、Configuration、ComponentScan、Import、ImportResource注解的類;
  • Import注解中指定的類、被Bean注解標注的方法所在的類;
  • 實現了ImportBeanDefinitionRegistrar接口,并且在registerBeanDefinitions方法中調用registry直接注冊的類;
  • 實現了ImportSelector接口,并且在selectImports方法中返回的字符串對應的類;
  • 直接調用register方法;
  • 另外Spring還提供了一個擴展,可以讓開發者自己指定需要被管理的類對應的類型:通過往includeFilters中添加注解類類型。

我們分析源碼,第一步得找到它的入口,Spring整合MyBatis的入口,毫無疑問是MapperScan這個注解,在MapperScan注解上包含Import(MapperScannerRegistrar.class)注解,Spring整合MyBatis正是用了Import和ImportBeanDefinitionRegistrar的方式。我們先通過一張流程圖來了解下整體流程,然后再慢慢品。

圖片

我們來看MapperScannerRegistrar這個類的繼承關系圖:

圖片

MapperScannerRegistrar是ImportBeanDefinitionRegistrar的實現類,Spring會去調用這個類的registerBeanDefinitions方法添加beanDefinition,這個方法中具體做了些什么呢:

獲取MapperScan注解的配置信息,比如basePackages、annotationClass,basePackages表示需要掃描的路徑,annotationClass則是指定了增加了這種注解類的類需要被Spring進行管理,比如增加了Mapper注解的類需要被Spring管理。

生成MapperScannerConfigurer這個類型的beanDefinition,并且把MapperScan注解的配置信息添加到該beanDefinition的屬性集合中。

后續Spring就會基于這個MapperScannerConfigurer做一系列文章,看下它的繼承關系:

圖片

它是BeanDefinitionRegistryPostProcessor的實現類,是一個BeanFactory后置處理器,Spring會調用該類的postProcessBeanDefinitionRegistry方法來添加beanDefinition的操作,MapperScannerConfigurer這個類中具體實現如下:

圖片

它定義了ClassPathMapperScanner這個掃描器,然后使用這個掃描器來掃描類,掃描哪些類呢?掃描有Mapper注解的類,看它的關系知道,它是ClassPathBeanDefinitionScanner的子類,而spring則是使用ClassPathBeanDefinitionScanner來進行掃描的。

圖片

為什么ClassPathMapperScanner能夠掃描到帶有Mapper注解的類呢?看上面代碼,就是通過調用registerFilters方法來添加includeFilter(實際類型是:TypeFilter),這個就是Spring提供的擴展點,讓咱們自己來指定需要被掃描的類,這里使用的是MappScan注解中annotationClass屬性配置的注解類型,我們這里配置了Mapper,所以調用scan方法開啟掃描后,Spring就會將包含Mapper注解的類掃描為BeanDefinition。注意這里的掃描能力還是調用Spring的掃描器來實現的,ClassPathMapperScanner并沒有修改,只是當掃描完成后,ClassPathMapperScanner會對掃描出的BeanDefinition進行重新處理,主要是把原來的BeanClass修改成了MapperFactoryBean.class:

圖片

而這個MapperFactoryBean是FactoryBean的實現類,老鐵們,FactoryBean這種Bean有什么特點?這個可是面試的高發點哦。

做個小小的總結:Spring掃描到有Mapper注解的類,生成BeanDefinition,并且將這一類BeanDefinition的BeanClass的值修改為MapperFactoryBean,也就是說它的類型不再是咱們自己編寫的Mapper接口了,而是一個FactoryBean,這樣Spring就能做妖了。

二、Mapper注解的類是接口

那如何實例化呢?

到這一步,其實老鐵們也大概清楚了,Spring在實例化Mapper實例時,實際上首先會實例化MapperFactoryBean,然后再調用它的getObject方法。我們知道在Java里面接口是肯定不能被實例化的,那這個被實例化的對象只能是一個代理對象,所以我們有理由猜想這個getObject方法應該是用來創建代理對象的。要創建代理對象,得從以下兩個方面著手:

1.準備工作

這里Spring準備的是接口類型和創建代理對象的代理工廠。具體如何準備的呢?來看上述MapperFactoryBean類型的整體繼承關系:

圖片

它實現了InitializingBean,于是可以知道,在MapperFactoryBean初始化完成后,Spring會調用它的afterPropertiesSet方法,從而會執行到checkDaoConfig方法:

圖片

在該方法中調用configuration的addMapper方法,這個方法里面到底做了啥?

圖片

看出門道了嗎?其實就是使用Mapper的接口類型作為key,MapperProxyFactory做為value,然后添加到mapperRegistry對象的Map集合中,注意這個type同時也是MapperProxyFactory對象的構造參數哦。

2.實例化

上述動作已經準備好了,接下來就應該是創建了。Spring在創建完成MapperFactoryBean對象后,最終會調用它的getObject方法來獲得真實的對象:

圖片

圖片

圖片

getObject方法中,會調用getMapper方法,該方法中從knowMappers這個Map集合中拿到MapperProxyFactory對象,這個對象不就是我們在準備階段添加的嘛!它就是用來創建代理對象的工廠。

圖片

從上面代碼中也不難看出,確實是為咱們自己的接口創建了代理對象,而代理類的處理類則是MapperProxy對象,也就是說對所有接口對象的調用,都會進入MapperProxy的Invoke方法,至此Spring成功對接MyBatis。

作者介紹

波哥,互聯行業從業10余年,先后擔任項目總監及架構師。目前專攻技術,喜歡研究技術原理。技術全面,主攻java,精通JVM底層機制及Spring全家桶底層框架原理,熟練掌握當前主流的中間件、服務網格等技術原理。

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2021-11-10 11:37:48

Spring整合 Mybatis

2020-11-09 10:16:41

Mybatis

2018-11-09 09:34:05

面試Spring Clou底層

2024-01-29 08:00:00

架構微服務開發

2023-04-28 08:30:56

MyBatis架構API

2021-08-29 07:41:48

數據HashMap底層

2017-05-12 15:47:15

Spring BootMybatis Ann Web

2024-06-13 00:54:19

2023-01-04 07:54:03

HashMap底層JDK

2024-01-05 09:00:00

SpringMVC軟件

2020-11-05 11:14:29

Docker底層原理

2021-08-31 07:36:22

LinkedListAndroid數據結構

2021-07-05 07:51:43

JVM底層Python

2021-07-23 13:34:50

MySQL存儲InnoDB

2023-10-18 10:55:55

HashMap

2022-12-19 08:00:00

SpringBootWeb開發

2009-06-19 10:00:37

Struts和Spri

2016-12-14 09:03:34

springhibernate異常

2009-06-18 15:24:08

Spring OSGi

2022-11-04 09:43:05

Java線程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品免费国产一区二区三区 | 天天天天操 | 日韩一级精品视频在线观看 | 国产午夜精品一区二区三区在线观看 | 日本成人二区 | 天天操夜夜爽 | 国产成人啪免费观看软件 | 日韩福利在线观看 | 欧美精品乱码99久久影院 | 成人免费视频7777777 | 亚洲国产成人精 | 国外成人免费视频 | 久久精品国产99国产精品亚洲 | 亚洲综合在线视频 | 国产精品视频区 | 性高湖久久久久久久久 | 一级片在线观看视频 | 羞视频在线观看 | 日韩成年人视频在线 | 亚洲狠狠丁香婷婷综合久久久 | 久久精品青青大伊人av | 国产视频线观看永久免费 | 日韩有码一区 | 91精品国产欧美一区二区成人 | 国产乱码久久久久久一区二区 | 在线免费观看日本 | 国产综合精品 | 免费在线观看一区二区 | 欧美 日韩 在线播放 | 看亚洲a级一级毛片 | 日韩2020狼一二三 | 欧美女优在线观看 | 天天精品在线 | 成人av一区二区三区 | 国产成人精品网站 | 亚洲成人精选 | av一级毛片 | www亚洲精品 | 成人亚洲精品 | 日韩一区二区黄色片 | 日本不卡在线视频 |