本文我们主要研究一下@ComponentScan
的解析过程。
如下所示,在ConfigurationClassParser
的doProcessConfigurationClass
方法中会对@ComponentScan注解进行处理。
// Process any @ComponentScan annotations //扫描sourceClass上配置的@ComponentScans @ComponentScan注解得到每一个注解属性 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); //如果不为空且不需要跳过,则对每一个componentScan 进行处理 if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { for (AnnotationAttributes componentScan : componentScans) { // The config class is annotated with @ComponentScan -> perform the scan immediately //使用解析器对注解进行解析得到扫描的BeanDefinitionHolder集合 Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); // Check the set of scanned definitions for any further config classes and parse recursively if needed //对每一个BeanDefinitionHolder 判断其是否可以作为候选配置类,如果是则触发配置类解析过程 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); if (bdCand == null) { bdCand = holder.getBeanDefinition(); } //这里判断是否为候选配置类,如果是则触发配置类解析过程 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { parse(bdCand.getBeanClassName(), holder.getBeanName()); } } } }
可以看到这里首先使用componentScanParser解析每一个componentScan 得到BeanDefinitionHolder 的集合scannedBeanDefinitions。然后对集合进行遍历如果可以作为候选配置类,则触发配置类的解析流程。配置类解析过程我们本文不再赘述,我们看一下this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
这里componentScanParser是ComponentScanAnnotationParser。
① parse方法
// ComponentScanAnnotationParser public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { // 实例化扫描器 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); //本文这里得到的是AnnotationBeanNameGenerator Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); // true boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); //设置beanNameGenerator scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass)); //默认是DEFAULT ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); if (scopedProxyMode != ScopedProxyMode.DEFAULT) { scanner.setScopedProxyMode(scopedProxyMode); } else { // 本文这里得到的是AnnotationScopeMetadataResolver Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); } //默认是**/*.class" scanner.setResourcePattern(componentScan.getString("resourcePattern")); //解析includeFilters for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addIncludeFilter(typeFilter); } } //解析excludeFilters for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { for (TypeFilter typeFilter : typeFiltersFor(filter)) { scanner.addExcludeFilter(typeFilter); } } //是否懒加载,默认为false boolean lazyInit = componentScan.getBoolean("lazyInit"); if (lazyInit) { scanner.getBeanDefinitionDefaults().setLazyInit(true); } //解析扫描的基础包basePackages Set<String> basePackages = new LinkedHashSet<>(); String[] basePackagesArray = componentScan.getStringArray("basePackages"); for (String pkg : basePackagesArray) { // 如果有占位符则从环境里面解析 String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); Collections.addAll(basePackages, tokenized); } //解析basePackageClasses得到包名放到basePackages中 for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { basePackages.add(ClassUtils.getPackageName(clazz)); } // 如果为空,则添加当前declaringClass所在包路径 if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); } //添加排他过滤器 scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { @Override protected boolean matchClassName(String className) { return declaringClass.equals(className); } }); //触发扫描,最终得到过滤后的BeanDefinition集合。 return scanner.doScan(StringUtils.toStringArray(basePackages)); }
方法如上所示,首先实例化得到一个ClassPathBeanDefinitionScanner
,然后解析当前注解的属性最终得到basePackages对其进行扫描,最终得到过滤后的BeanDefinition集合。
② doScan扫描
这里basePackages是基础包路径,从这里面遍历扫描候选组件然后注册为BeanDefinition。
// ClassPathBeanDefinitionScanner protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Assert.notEmpty(basePackages, "At least one base package must be specified"); Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); //遍历basePackages for (String basePackage : basePackages) { //获取当前basePackage下的候选组件,会进行双重过滤 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); //遍历候选组件 for (BeanDefinition candidate : candidates) { //首先为BeanDefinition设置scope,默认是singleton // AnnotationScopeMetadataResolver ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); //获取当前BeanDefinition对应的beanName String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); //对BeanDefinition做后置处理 if (candidate instanceof AbstractBeanDefinition) { //对BeanDefinition做一些处理如设置autowireCandidate、lazyInit、setAutowireMode等 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); } if (candidate instanceof AnnotatedBeanDefinition) { //BeanDefinition的通用后置处理 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } //检测BeanDefinition是否不存在或是否可共存 if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); //如果ScopedProxyMode不为NO,则尝试创建代理,默认为NO definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); //注册BeanDefinition到BeanFactory中 registerBeanDefinition(definitionHolder, this.registry); } } } return beanDefinitions; }
方法逻辑梳理如下:
遍历basePackages
获取当前basePackage下的候选组件,会进行双重过滤
遍历候选组件
首先为BeanDefinition设置scope,默认是singleton
获取当前BeanDefinition对应的beanName
对BeanDefinition做后置处理
检测BeanDefinition是否不存在或是否可共存
如果ScopedProxyMode不为NO,则尝试创建代理,默认为NO
注册BeanDefinition到BeanFactory中
③ 获取候选组件
// ClassPathScanningCandidateComponentProvider#findCandidateComponents public Set<BeanDefinition> findCandidateComponents(String basePackage) { //本文这里componentsIndex 为null if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { //走了该分支 return scanCandidateComponents(basePackage); } }
扫描候选组件方法如下,本质就是根据基础包路径扫描得到一个Resource数组然后进行后滤。过滤后的实例化得到一个BeanDefinition,再次过滤得到最终需要的结果。
// ClassPathScanningCandidateComponentProvider#scanCandidateComponents private Set<BeanDefinition> scanCandidateComponents(String basePackage) { Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { //classpath*: +包路径+ / + **/*.class //比如classpath*:com/recommend/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; //解析路径,得到一个个具体的资源 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); //遍历resources,将每一个Resource 生成为一个ScannedGenericBeanDefinition for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } //判断资源是否可读的 if (resource.isReadable()) { try { //metadataReader包括了resource和annotationMetadata MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); //判断是否为候选组件,这里会应用excludeFilters、includeFilters //第一次过滤 if (isCandidateComponent(metadataReader)) { //实例化BeanDefinition ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); //设置source resource sbd.setResource(resource); sbd.setSource(resource); //第二次过滤 //(非接口非抽象||抽象&Lookup标注方法)&&isIndependent 是独立的 if (isCandidateComponent(sbd)) { if (debugEnabled) { logger.debug("Identified candidate component class: " + resource); } candidates.add(sbd); } else { if (debugEnabled) { logger.debug("Ignored because not a concrete top-level class: " + resource); } } } else { if (traceEnabled) { logger.trace("Ignored because not matching any filter: " + resource); } } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } else { if (traceEnabled) { logger.trace("Ignored because not readable: " + resource); } } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
可以看到这里首先会解析得到packageSearchPath,然后使用ResourcePatternResolver对packageSearchPath进行处理得到一个Resource[] resources数组。这个数组也就是基础包路径下的一个个类,对每个Resource进行双重过滤后将合适的ScannedGenericBeanDefinition放到candidates中最后返回给上游。
④ BeanDefinition的后置处理
如下所示得到候选组件后,我们会对每一个candidate做处理。
其中下面两行是对BeanDefinition做处理。
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
4.1 postProcessBeanDefinition
这个主要是为beanDefinition设置默认属性值。
// ClassPathBeanDefinitionScanner#postProcessBeanDefinition protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) { // 设置默认属性 beanDefinition.applyDefaults(this.beanDefinitionDefaults); //尝试设置AutowireCandidate if (this.autowireCandidatePatterns != null) { beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName)); } } // AbstractBeanDefinition#applyDefaults 设置默认值 public void applyDefaults(BeanDefinitionDefaults defaults) { //默认是null Boolean lazyInit = defaults.getLazyInit(); if (lazyInit != null) { setLazyInit(lazyInit); } // 默认是AUTOWIRE_NO 0 setAutowireMode(defaults.getAutowireMode()); //默认是DEPENDENCY_CHECK_NONE 0 setDependencyCheck(defaults.getDependencyCheck()); setInitMethodName(defaults.getInitMethodName()); setEnforceInitMethod(false); setDestroyMethodName(defaults.getDestroyMethodName()); setEnforceDestroyMethod(false); }
4.2 processCommonDefinitionAnnotations
最终会来到AnnotationConfigUtils
的processCommonDefinitionAnnotations
方法。主要用来处理@Lazy、@Primary、@DependsOn、@Role以及@Description
注解信息。
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { //获取Lazy注解信息 AnnotationAttributes lazy = attributesFor(metadata, Lazy.class); 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")); } } //获取@Primary注解信息 if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } //获取@DependsOn注解信息 AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); } // 获取@Role注解信息 AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null) { abd.setRole(role.getNumber("value").intValue()); } //获取@Description注解信息 AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null) { abd.setDescription(description.getString("value")); } }