Mybatis是如何向Spring注冊(cè)Mapper的
1. 前言
有時(shí)候我們需要自行定義一些注解來標(biāo)記某些特定功能的類并將它們注入Spring IoC容器。比較有代表性的就是Mybatis的Mapper接口。假如有一個(gè)新的需求讓你也實(shí)現(xiàn)類似的功能你該如何下手呢?今天我們就從Mybatis的相關(guān)功能入手來學(xué)習(xí)其思路并為我所用。
2. Mybatis Mapper注冊(cè)機(jī)制
Mybatis結(jié)合Spring將Mapper注冊(cè)到Spring IoC的機(jī)制是這樣的:

其實(shí)里面涉及到Spring和Mybatis的知識(shí)點(diǎn)還是比較多的,但是我們只要梳理出來流程就比較容易理解和掌握。所以閱讀源碼的精髓在于先掌握一片葉子的脈絡(luò),然后各個(gè)擊破去梳理其走向。所以胖哥梳理出左邊的就是右邊的“脈絡(luò)”,接下來我們就一步步剖析它們。
3. ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar是一個(gè)非常重要的接口,凡是要把第三方整合到Spring的開發(fā)者都應(yīng)該掌握這個(gè)接口。這接口用來動(dòng)態(tài)的注冊(cè)某一些具有相同特征的一批類到Spring IoC,用法有點(diǎn)類似 ImportSelector接口,借助于@Import注解“附著在”自定義的注解上,就像Mybatis-Spring的用法一樣。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public?@interface?MapperScan?{
????//?省略
}
也可以直接附著到標(biāo)記有@Configuration或者具有相同功能的配置類上。
@Import(MapperScannerRegistrar.class)
@Configuration
public?class?MyConfig?{
}
它只有一個(gè)方法:
void?registerBeanDefinitions(AnnotationMetadata?importingClassMetadata,?BeanDefinitionRegistry?registry);
其中參數(shù)importingClassMetadata包含了@Import所依附的配置類上的所有注解。這意味著我們可以拿到對(duì)應(yīng)注解的元信息并作為我們動(dòng)態(tài)導(dǎo)入的判斷依據(jù),上面就是從@MapperScan獲取了Mapper所在的包以及其它信息。而BeanDefinitionRegistry就是用來注冊(cè)Spring Bean的。那么到底是如何注冊(cè)的呢?這就該下一個(gè)主角登場(chǎng)了。
4. BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,BeanFactoryPostProcessor的作用是在Spring Bean的定義信息已經(jīng)加載但還沒有初始化的時(shí)候執(zhí)行postProcessBeanFactory()來處理一些額外的邏輯,而BeanDefinitionRegistryPostProcessor的作用是在BeanFactoryPostProcessor增加了一個(gè)前置處理,當(dāng)一個(gè)Bean實(shí)現(xiàn)了該接口后,始化前先執(zhí)行該接口的postProcessBeanDefinitionRegistry()方法,然后再執(zhí)行其父類的方法postProcessBeanFactory()。這樣就把一個(gè)Spring Bean的初始化周期更加細(xì)化,讓我們?cè)诟鱾€(gè)階段有定制它的可能。
但是對(duì)于本文來說這個(gè)類其實(shí)是可以忽略的,該類只是觸發(fā)了批量掃描注入邏輯,它并沒有實(shí)際參與掃描注入。
5. ClassPathBeanDefinitionScanner
從名字上來看這個(gè)類就是在類路徑下掃描Bean定義并將符合條件的批量通過BeanDefinitionRegistry注冊(cè)到Spring IoC。它提供了一些默認(rèn)的過濾器來檢出需要被注入Spring IoC的Bean,默認(rèn)使用JSR 250和JSR 330的兩個(gè)注解。當(dāng)然你可以通過addIncludeFilter來新增被包含的Bean,或者addExcludeFilter來排除一些Bean。然后只需要調(diào)用其scan方法對(duì)特定的包進(jìn)行掃描注入。
6. FactoryBean
就像Mybatis的Mapper一樣,它們具有共同的特點(diǎn)的同時(shí)也有一些差異。所以使用FactoryBean接口來創(chuàng)建這些Mapper再合適不過了。關(guān)于FactoryBean我在 Spring 中的FactoryBean 與BeanFactory 一文中專門來講解它,有興趣的可以去了解。
但是
FactoryBean并不是動(dòng)態(tài)掃描注入的必選步驟。
7. 總結(jié)
本文通過對(duì)Mybatis的注入機(jī)制進(jìn)行了分析,目的是研究ImportBeanDefinitionRegistrar的生命周期和使用。如何通過它來編寫我們自己的注入邏輯才是最重要的,后續(xù)我會(huì)講一些ImportBeanDefinitionRegistrar的實(shí)際應(yīng)用,請(qǐng)持續(xù)關(guān)注: 碼農(nóng)小胖哥。
—?【 THE END 】— 本公眾號(hào)全部博文已整理成一個(gè)目錄,請(qǐng)?jiān)诠娞?hào)里回復(fù)「m」獲??! 3T技術(shù)資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號(hào)內(nèi)回復(fù)「1024」,即可免費(fèi)獲?。?!
