基于Spring整合mybatis的mapper生成過程
Spring整合mybatis的mapper生成過程

mapperScannerConfigurer實(shí)現(xiàn)了BeandifinitionRegistryPostProcessor
后置處理beanFactory時(shí)會(huì)調(diào)用其postProcessBeanDefinitionRegistry

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
scanner.setMapperFactoryBeanClass(this.mapperFactoryBeanClass);
scanner.registerFilters();
//掃描包集合,注冊(cè)mapper的beandifinition
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
ClassPathMapperScanner#doScan
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
LOGGER.warn(() -> "No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
//會(huì)對(duì)bean信息進(jìn)行一些更改和添加,如設(shè)置propertyValues,向其中添加sqlsessionFactory等屬性信息等
processBeanDefinitions(beanDefinitions);
}
return beanDefinitions;
}ClassPathBeanDefinitionScanner#doScan
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
//遍歷集合掃描包,獲取包下的可用的mapper信息
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
} 
如上在進(jìn)行包掃描時(shí),會(huì)調(diào)用ClassPathBeanDefinitionScanner#doScan,進(jìn)行beanDefinition的掃描和注冊(cè)
執(zhí)行完后調(diào)用ClassPathMapperScanner#processBeanDefinitions
private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
//有省略部分
//這里有遍歷所有mapper
//將所有mapper的beanClass改為了mapperFactoryBean,最后生成的bean也是該類型的,只有在用到的
//時(shí)候才會(huì)調(diào)用getObject生成mapper
definition.setBeanClass(this.mapperFactoryBeanClass);
//接下來是添加一些MapperFactoryBean的屬性信息到beandefinition里,在生成實(shí)例的時(shí)候,會(huì)根據(jù)
//此處傳入的值來進(jìn)行具體設(shè)置,如sqlsessionFactory
definition.getPropertyValues().add("addToConfig", this.addToConfig);
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
} else if (this.sqlSessionTemplate != null) {
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
}
}確定了所有的mapper的beanDefinition為MapperFactoryBean類型后,
確定在生成的bean皆為MapperFactoryBean,在getBean時(shí)會(huì)調(diào)用MapperFactoryBean#getObject

mapperInterface是在MapperFactoryBean創(chuàng)建時(shí),會(huì)調(diào)用有參構(gòu)造創(chuàng)建實(shí)例,值是創(chuàng)建是


構(gòu)造方法參數(shù)的獲取從mdb中

創(chuàng)建除了傳入mapperInterface,還會(huì)在設(shè)置屬性值時(shí)調(diào)用MapperFactoryBean的父類SqlSessionDaoSupport#setSqFactory 將mdb中的sqlsessionfactory傳入其中

mdb的sqlsessionFactory信息來歷

查看方法棧調(diào)用,可以看到在開始填充屬性時(shí)會(huì)去mdb中判斷是否有propertyValue,如果有就返回,這就是之前掃描mapper后ClassPathMapperScanner#processBeanDefinitions對(duì)mdb的一些設(shè)置
在創(chuàng)造service時(shí),如果有@Autowire 注入mapper,在createBean時(shí)會(huì)調(diào)用getObject
mdb只有一份,可得sqlsessionfactory即只有一份,sqlsessionTemplate一個(gè)mapper一份
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
spring mvc DispatcherServlet之前端控制器架構(gòu)詳解
這篇文章主要為大家詳細(xì)介紹了spring mvc DispatcherServlet之前端控制器架構(gòu),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
java?freemarker實(shí)現(xiàn)動(dòng)態(tài)生成excel文件
這篇文章主要為大家詳細(xì)介紹了java如何通過freemarker實(shí)現(xiàn)動(dòng)態(tài)生成excel文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12
Java局部?jī)?nèi)部類原理與用法實(shí)例分析
這篇文章主要介紹了Java局部?jī)?nèi)部類原理與用法,結(jié)合實(shí)例形式分析了Java局部?jī)?nèi)部類功能、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-09-09
Java Swing 非常漂亮外觀Nimbus的使用方法實(shí)例
Java Swing 非常漂亮外觀Nimbus的使用方法實(shí)例,需要的朋友可以參考一下2013-02-02
SpringBoot+Redis+Lua防止IP重復(fù)防刷攻擊的方法
本文主要介紹了SpringBoot+Redis+Lua防止IP重復(fù)防刷攻擊的方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12

