Mybatis是如何將Mapper介面註冊到Spring IoC的
- 2020 年 9 月 20 日
- 筆記

1. 前言
有時候我們需要自行定義一些註解來標記某些特定功能的類並將它們注入Spring IoC容器。比較有代表性的就是Mybatis的Mapper介面。假如有一個新的需求讓你也實現類似的功能你該如何下手呢?今天我們就從Mybatis的相關功能入手來學習其思路並為我所用。
2. Mybatis Mapper註冊機制
Mybatis結合Spring將Mapper註冊到Spring IoC的機制是這樣的:

其實裡面涉及到Spring和Mybatis的知識點還是比較多的,但是我們只要梳理出來流程就比較容易理解和掌握。所以閱讀源碼的精髓在於先掌握一片葉子的脈絡,然後各個擊破去梳理其走向。所以胖哥梳理出左邊的就是右邊的「脈絡」,接下來我們就一步步剖析它們。
3. ImportBeanDefinitionRegistrar
ImportBeanDefinitionRegistrar是一個非常重要的介面,凡是要把第三方整合到Spring的開發者都應該掌握這個介面。這介面用來動態的註冊某一些具有相同特徵的一批類到Spring IoC,用法有點類似 ImportSelector介面,藉助於@Import註解「附著在」自定義的註解上,就像Mybatis-Spring的用法一樣。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(MapperScannerRegistrar.class)
@Repeatable(MapperScans.class)
public @interface MapperScan {
// 省略
}
也可以直接附著到標記有@Configuration或者具有相同功能的配置類上。
@Import(MapperScannerRegistrar.class)
@Configuration
public class MyConfig {
}
它只有一個方法:
void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
其中參數importingClassMetadata包含了@Import所依附的配置類上的所有註解。這意味著我們可以拿到對應註解的元資訊並作為我們動態導入的判斷依據,上面就是從@MapperScan獲取了Mapper所在的包以及其它資訊。而BeanDefinitionRegistry就是用來註冊Spring Bean的。那麼到底是如何註冊的呢?我們接著往下看。
4. BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子介面,BeanFactoryPostProcessor的作用是在Spring Bean的定義資訊已經載入但還沒有初始化的時候執行postProcessBeanFactory()來處理一些額外的邏輯,而BeanDefinitionRegistryPostProcessor的作用是在BeanFactoryPostProcessor增加了一個前置處理,當一個Bean實現了該介面後,始化前先執行該介面的postProcessBeanDefinitionRegistry()方法,然後再執行其父類的方法postProcessBeanFactory()。這樣就把一個Spring Bean的初始化周期更加細化,讓我們在各個階段有訂製它的可能。
但是對於本文來說這個類其實是可以忽略的,該類只是觸發了批量掃描注入邏輯,它並沒有實際參與掃描注入。
5. ClassPathBeanDefinitionScanner
從名字上來看這個類就是在類路徑下掃描Bean定義並將符合條件的批量通過BeanDefinitionRegistry註冊到Spring IoC。它提供了一些默認的過濾器來檢出需要被注入Spring IoC的Bean,默認使用JSR 250和JSR 330的兩個註解。當然你可以通過addIncludeFilter來新增被包含的Bean,或者addExcludeFilter來排除一些Bean。然後只需要調用其scan方法對特定的包進行掃描注入。
6. FactoryBean
就像Mybatis的Mapper一樣,它們具有共同的特點的同時也有一些差異。所以使用FactoryBean介面來創建這些Mapper再合適不過了。關於FactoryBean我在 Spring 中的FactoryBean 與BeanFactory 一文中專門來講解它,有興趣的可以去了解。
但是
FactoryBean並不是動態掃描注入的必選步驟。
7. 總結
本文通過對**Mybatis **的注入機制進行了分析來研究ImportBeanDefinitionRegistrar的生命周期和使用。如何通過它來編寫我們自己的注入邏輯才是最重要的,後續我會講一些這方面的實際應用,請持續關注: 碼農小胖哥。
關注公眾號:Felordcn 獲取更多資訊

