Spring源码之基于@ComponentScan生成BeanDefinition

  • Post author:
  • Post category:其他




一、前言

本文用到的是Spring5.2.4版本的源码。

Spring会根据配置类上

@ComponentScan

注解提供的扫描路径加载Bean,扫描加载的核心方法是

ClassPathBeanDefinitionScanner.doScan()

在讲一下这个核心方法是在spring启动中的哪个环节执行的。


SpringBoot环境

主入口类的@SpringBootApplication注解中就包含@SpringBootConfiguration(可以理解成@Configuration的子类注解)和@ComponentScan注解,扫描的路径默认是当前主入口类的所在包。

在refresh()中的

invokeBeanFactoryPostProcessors(beanFactory);

中执行。

invokeBeanFactoryPostProcessors

负责执行所有的BeanFactoryPostProcessor。而派生类ConfigurationClassPostProcessor负责处理所有的@Configuration配置类。其中有一个环节是处理配置上的@ComponentScan注解,就会调用到我们上面说的核心方法

doScan()

.



二、主要流程


doScan():

生成并设置BeanDefinition

在这里插入图片描述


流程如下:

  1. 调用

    findCandidateComponents()

    找到所有的BeanDefinition候选者Set
  2. 遍历所有的BeanDefinition候选者

  3. 获取@Scope注解的信息并给BeanDefinition设置Scope属性
  4. 获取Bean的名字
  5. 添加些默认的Bean定义信息

  6. 解析@Lazy、@Primary、@DependsOn、@Role、@Description注解的信息
  7. 封装成BeanDefinitionHolder

  8. 根据Scope中的proxyMode判断是否需要创建代理
  9. 注册到beanDefinitionMap


findCandidateComponents():

是doScan中的一个主要方法,作用是加载并过滤所有的class,得到BeanDefinition的全部候选者,生成beanDefinition。

在这里插入图片描述


流程如下:


11. 获取扫描的路径

12. 获取符合规则的所有class的Resource

13. 根据Resource获取MetadataReader

14.

根据excludeFilters、includeFilters以及@Conditional过滤MetadataReader


15. 基于metadataReader生成ScannedGenericBeanDefinition

16.

根据MetadataReader过滤BeanDefinition,过滤掉接口,过滤掉内部类,过滤掉没有@Lookup方法的抽象类


17. 将符合条件的BeanDefinition填加到集合中



三、源码解析


doScan:

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        // basePackages为空抛出异常
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		// 定义BeanDefinitionHolder的集合
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		// 遍历扫描路径
		for (String basePackage : basePackages) {
		    // 找出所有的BeanDefinition候选者
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			// 遍历所有的BeanDefinition
			for (BeanDefinition candidate : candidates) {
			    // 读取@Scope注解的信息
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				// 设置Scope
				candidate.setScope(scopeMetadata.getScopeName());
				// 获取bean的名字
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				// 设置一些默认信息,例如默认的initmethod、destroymethod
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				// 解析@Lazy、@Primary、@DependsOn、@Role、@Description注解的信息
				if (candidate instanceof AnnotatedBeanDefinition) {
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 判断容器中是否已存在该beanDefinition
				if (checkCandidate(beanName, candidate)) {
				    // 封装成BeanDefinitionHolder 
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					// 根据@Scope中的proxyMode值判断是否需要生成代理
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					// 注册到beanDefinitionMap
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}


findCandidateComponents:

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    // 如果存在索引,并且索引的类都可以成为bean。使用带有索引的方式生成BeanDefinition。(用的较少,源码else里面的很类似,可能性能相对高一点,这里不详细分析)
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
        return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    }
    else {
        // 扫描包含Component注解的可成为Bean的方法:大部分情况下走的扫描方法
        return scanCandidateComponents(basePackage);
    }
}
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
		    // 获取扫描class的路径规则,格式:classpath*:com/demo/simLogin/**/*.class
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
			// 获取符合规则的所有class的Resource
			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);
						// 根据excludeFilters、includeFilters以及@Conditional判断
						if (isCandidateComponent(metadataReader)) {
						    // 生成BeanDefinition
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							// 将当前资源保存
							sbd.setResource(resource);
							sbd.setSource(resource);
							// 过滤掉接口,过滤掉内部类,过滤掉没有@Lookup方法的抽象类
							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;
	}



版权声明:本文为qq_42878176原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。