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類型。