Spring的版本是5.0.9.release.java
先上一张图,以下图1.git
图1github
ClassPathBeanDefinitionScanner在哪使用到的呢,看以下List-1,AnnotationConfigApplicationContext的构造方法中,初始化了ClassPathBeanDefinitionScanner,为何传this进入呢,是由于ClassPathBeanDefinitionScanner的构造方法参数是BeanDefinitionRegistry类型的,ClassPathBeanDefinitionScanner要把扫描到是BeanDefinition注册到BeanDefinitionRegistry中。spring
List-1mybatis
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry { private final AnnotatedBeanDefinitionReader reader; private final ClassPathBeanDefinitionScanner scanner; /** * Create a new AnnotationConfigApplicationContext that needs to be populated * through {@link #register} calls and then manually {@linkplain #refresh refreshed}. */ public AnnotationConfigApplicationContext() { this.reader = new AnnotatedBeanDefinitionReader(this); this.scanner = new ClassPathBeanDefinitionScanner(this); } ...
ClassPathBeanDefinitionScanner的最重要的方法是scan(),scan()又调用doScan(),以下List-2app
List-2ide
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) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage);//1 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) {//2 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } if (checkCandidate(beanName, candidate)) {//3 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
findCandidateComponents(),作了不少事情,咱们来分析下,findCandidateComponents()调用scanCandidateComponents(),scanCandidateComponents()中会在basePackage前面加上"classpaths:",再加上后缀"**/*.class",以后用PathMatchingResourcePatternResolver获取该package下的全部类,并将每一个类封装为Resource,以下List-3,以后将每一个resource转换为MetadataReader,仔细看下1处isCandidateComponent(metadataReader)的处理,以下List-4,在List-4中,includeFilters默认添加了new AnnotationTypeFilter(Component.class),这意味着isCandidateComponent()方法中调用includeTypeFilter的TypeFilter.match时,只要这个类上标有@Component或者含有@Component的组合注解,那么这个类就会被视为Spring要处理的类来处理,不然不会考虑,includeTypeFilter的TypeFilter.match返回true时,以后调用isConditionMatch(),isConditionMatch方法中又调用conditionEvaluator的shuldSkip方法来判断是否将这个类注册到BeanFactory,conditionEvaluator.shuldSkip()方法处理的是@ConditionalOnXX的状况,好比CondtionalOnBean等,有上面的分析能够看出,先判断类上是否有@Component或者其组合注解,若是有再处理加了@ConditionalOn的状况,若是不符合则这个类不会解析为BeanDefinition,进而不会注册到BeanFactory中。post
List-3this
private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } if (resource.isReadable()) { try { MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); if (isCandidateComponent(metadataReader)) {//1 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); sbd.setResource(resource); sbd.setSource(resource); if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } ... } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
List-4lua
private final List<TypeFilter> includeFilters = new LinkedList<>(); private final List<TypeFilter> excludeFilters = new LinkedList<>(); ... protected void registerDefaultFilters() { this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false)); logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip. } try { this.includeFilters.add(new AnnotationTypeFilter( ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false)); logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning"); } catch (ClassNotFoundException ex) { // JSR-330 API not available - simply skip. } } ... protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException { for (TypeFilter tf : this.excludeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return false; } } for (TypeFilter tf : this.includeFilters) { if (tf.match(metadataReader, getMetadataReaderFactory())) { return isConditionMatch(metadataReader); } } return false; } ... private boolean isConditionMatch(MetadataReader metadataReader) { if (this.conditionEvaluator == null) { this.conditionEvaluator = new ConditionEvaluator(getRegistry(), this.environment, this.resourcePatternResolver); } return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata()); }
List-3中,将符合要求的类解析为BeanDefinition,并返回BeanDefiniton集合,回到了List-2中,会遍历获得的BeanDefinition集合,以后先判断是不是AbstractBeanDefinition类型,若是是则调用postProcessBeanDefinition来处理,以后判断是不是AnnotatedBeanDefinition类型,若是是则调用AnnotationConfigUtils.processCommonDefinitionAnnotations处理BeanDefinition,上述分析可知获得的BeanDefinition是ScannedGenericBeanDefinition,因此这个俩个处理方法都会被调用,咱们来看下AnnotationConfigUtils.processCommonDefinitionAnnotations,以下List-5:
List-5
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) { processCommonDefinitionAnnotations(abd, abd.getMetadata()); } static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);//1 if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } else if (abd.getMetadata() != metadata) { lazy = attributesFor(abd.getMetadata(), Lazy.class); if (lazy != null) { abd.setLazyInit(lazy.getBoolean("value")); } } if (metadata.isAnnotated(Primary.class.getName())) {//2 abd.setPrimary(true); } AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) {//3 abd.setDependsOn(dependsOn.getStringArray("value")); } if (abd instanceof AbstractBeanDefinition) { AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd; AnnotationAttributes role = attributesFor(metadata, Role.class);//4 if (role != null) { absBd.setRole(role.getNumber("value").intValue()); } AnnotationAttributes description = attributesFor(metadata, Description.class);//5 if (description != null) { absBd.setDescription(description.getString("value")); } } }
List-5中处理完了后,回到List-2,方法registerBeanDefinition将这个BeanDefinition注册到Spring容器中。
使用Spring-mybatis来集成mybatis时,MapperScannerConfigurer中使用ClassPathMapperScanner来扫描类,解析为BeanDefinition后,将BeanDefinition的beanClass类型设置为MapperFactoryBean——FactoryBean类型。