这章讲我们常用xml配置方式
MapperScannerConfigurer">
进入MapperScannerConfigurer,实现了BeanDefinitionRegistryPostProcessor, InitializingBean,重写了InitializingBean#afterPropertiesSet方法,不过没什么具体逻辑。我们直接看BeanDefinitionRegistryPostProcessor的实现。
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {MapperScannerConfigurer,让它扫描特定的包,自动帮我们成批地创建映射器。这样就大大减少了配置的工作量。
basePackage属性是让你为映射器接口文件设置基本的包路径。可以使用分号或逗号作为分隔符设置多于一个的包路径。每个映射器都会在指定的包路径中递归地被搜索到。被发现的映射器将会使用spring对自动侦测组件默认的命名策略来命名。也就是说,如果没有发现注解,它就会使用映射器的非大写的非完全限定类名。如果发现了@Component或JSR-330@Named注解,它会获取名称。
@Override 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.registerFilters(); //真正执行的 指定包名路径 scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS)); }
进入org.springframework.context.annotation.ClassPathBeanDefinitionScanner#scan
public int scan(String... basePackages) { //获取已经注册到ioc的bean数量 int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); //执行扫描 doScan(basePackages); // Register annotation config processors, if necessary. if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } //返回新建的bean有多少 return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
doScan方法在上一章已经出现过。这里只是复制一下
protected SetdoScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set beanDefinitions = new LinkedHashSet() ; //获取配置的路径下面所有的mapper全限定类名 for (String basePackage : basePackages) { Setcandidates = findCandidateComponents(basePackage) ; for (BeanDefinition candidate : candidates) { ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); //获取beanName String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (candidate instanceof AbstractBeanDefinition) { postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } //是否懒加载、是否为主键等 if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //是否beanName查看是否存在以及注册过 if (checkCandidate(beanName, candidate)) { //包装一下 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); //将入到当前列表中 beanDefinitions.add(definitionHolder); //注册到IOC中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
上一篇: Spring-Mybatis 注解连接器 MapperScannerRegistrar