postProcessBeanDefinitionRegistry
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware { public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { if (this.processPropertyPlaceHolders) { this.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); if (StringUtils.hasText(this.lazyInitialization)) { scanner.setLazyInitialization(Boolean.valueOf(this.lazyInitialization)); } if (StringUtils.hasText(this.defaultScope)) { scanner.setDefaultScope(this.defaultScope); } scanner.registerFilters(); scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n")); } }MapperScannerConfigurer在包org.mybatis.spring.mapper下.
这里会调用ClassPathMapperScanner.scan(),而ClassPathMapperScanner又继承了ClassPathBeanDefinitionScanner,所以这里scan()会调用ClassPathBeanDefinitionScanner.scan(), 而ClassPathBeanDefinitionScanner.scan() 第二句代码又调用了this.doScan(basePackages), this.doScan()又调用了ClassPathMapperScanner.doScan(), 而这个方法第一句代码又调用了super.doScan(basePackages),父子类来回互相调用,有点晕头转向的。
org.mybatis.spring.mapper.ClassPathMapperScanner
org.springframework.context.annotation.ClassPathBeanDefinitionScanner这个类在spring-context.jar
ClassPathMapperScannerClassPathBeanDefinitionScanner#scan
public int scan(String... basePackages) { int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); this.doScan(basePackages); if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } return this.registry.getBeanDefinitionCount() - beanCountAtScanStart; }ClassPathMapperScanner#doScan()
这个方法里在mybatis自动配置算比较重要的一个方法,也就是帮助我们自动配置MapperFactoryBean, 会把根据basePackage注册进Spring容器的BeanDefinition的beanClass设置成MapperFactoryBean。
ClassPathBeanDefinitionScanner#doScan()
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet(); String[] var3 = basePackages; int var4 = basePackages.length; for(int var5 = 0; var5 < var4; ++var5) { String basePackage = var3[var5]; //这个方法会扫描指定basePackage下被@Mapper注解标注的接口 Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage); Iterator var8 = candidates.iterator(); while(var8.hasNext()) { BeanDefinition candidate = (BeanDefinition)var8.next(); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); //这里获取beanName, 默认值是类名首字母小写 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate); } //检查对应的Mapper接口是否被注册进Spring容器中。 if (this.checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); this.registerBeanDefinition(definitionHolder, this.registry); } } } //这个集合返回以后 Spring容器会将里面的所有内容注册到容器中 return beanDefinitions; } ClassPathMapperScanner#processBeanDefinitions private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) { BeanDefinitionRegistry registry = this.getRegistry(); Iterator var4 = beanDefinitions.iterator(); while(var4.hasNext()) { BeanDefinitionHolder holder = (BeanDefinitionHolder)var4.next(); AbstractBeanDefinition definition = (AbstractBeanDefinition)holder.getBeanDefinition(); boolean scopedProxy = false; if (ScopedProxyFactoryBean.class.getName().equals(definition.getBeanClassName())) { definition = (AbstractBeanDefinition)Optional.ofNullable(((RootBeanDefinition)definition).getDecoratedDefinition()).map(BeanDefinitionHolder::getBeanDefinition).orElseThrow(() -> { return new IllegalStateException("The target bean definition of scoped proxy bean not found. Root bean definition[" + holder + "]"); }); scopedProxy = true; } String beanClassName = definition.getBeanClassName(); LOGGER.debug(() -> { return "Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + beanClassName + "' mapperInterface"; }); definition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName); //1.这里把普通接口设置成MapperFactoryBean definition.setBeanClass(this.mapperFactoryBeanClass); //2.是否把Mapper接口加入到Mybatis的Config当中去, 这里设置为true definition.getPropertyValues().add("addToConfig", this.addToConfig); definition.setAttribute("factoryBeanObjectType", beanClassName); boolean explicitFactoryUsed = false; //2.从核心容器里获取SqlSessionFactory赋值给MapperFactoryBean if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) { definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionFactory != null) { definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory); explicitFactoryUsed = true; } //3.从核心容器里获取SqlSessionTemplate赋值给MapperFactoryBean if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) { if (explicitFactoryUsed) { LOGGER.warn(() -> { return "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."; }); } definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName)); explicitFactoryUsed = true; } else if (this.sqlSessionTemplate != null) { if (explicitFactoryUsed) { LOGGER.warn(() -> { return "Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored."; }); } definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate); explicitFactoryUsed = true; } if (!explicitFactoryUsed) { LOGGER.debug(() -> { return "Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."; }); definition.setAutowireMode(2); } definition.setLazyInit(this.lazyInitialization); if (!scopedProxy) { if ("singleton".equals(definition.getScope()) && this.defaultScope != null) { definition.setScope(this.defaultScope); } if (!definition.isSingleton()) { BeanDefinitionHolder proxyHolder = ScopedProxyUtils.createScopedProxy(holder, registry, true); if (registry.containsBeanDefinition(proxyHolder.getBeanName())) { registry.removeBeanDefinition(proxyHolder.getBeanName()); } registry.registerBeanDefinition(proxyHolder.getBeanName(), proxyHolder.getBeanDefinition()); } } } }