【spring】Bean的生命周期之生成BeanDefinition

生成BeanDefinition

  • 本文源码基于spring-framework-5.3.10
  • Spring启动的时候会进行扫描。
  • 扫描入口:org.springframework.context.annotation.ClassPathBeanDefinitionScanner中public int scan(String... basePackages)方法
  • 扫描的核心方法:org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider中scanCandidateComponents(String basePackage)方法
  • 这一步主要作用是用来生成BeanDefinition,方便后续使用。

源码重点关注内容

  • BeanDefinition是如何生成的?
  • 什么样的对象会生成BeanDefinition。

生成BeanDefinition的主要流程

  • 首先,通过ResourcePatternResolver获得指定包路径下的所有.class文件(Spring源码中将此文件包装成了Resource对象)
  • 遍历每个Resource对象。
  • 利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader)。
  • 利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(条件注解并不能理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。)。
  • 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition。
  • 再基于metadataReader判断是不是对应的类是不是接口或抽象类。
  • 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集。

扫描的入口scan方法源码分析

/**
 * 扫描的入口
 */
public int scan(String... basePackages) {
	// 得到当前已经注册了多少个BeanDefinition
	int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
	// 尝试去扫描的逻辑,扫描的核心代码
	doScan(basePackages);

	// Register annotation config processors, if necessary.
	// 如有必要,注册注解配置处理器。
	// 这里不是本文的重点,主要对bean的信息进行完善
	if (this.includeAnnotationConfig) {
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
	// 返回:本次扫描时注册的bean的个数 = 当前bean的个数 - 没扫描前bean的个数 = 
	return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

扫描的核心doScan源码分析

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
	// 传入的包路径是空的!抛异常
	Assert.notEmpty(basePackages, "At least one base package must be specified");
	// 定义BeanDefinitionHolder(他是BeanDefinition封装了一层)的一个集合
	Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();

	// 遍历所有的包路径
	for (String basePackage : basePackages) {
		// 找到所有的BeanDefinition候选者
		Set<BeanDefinition> candidates = findCandidateComponents(basePackage);

		// 遍历所有的BeanDefinition候选者
		for (BeanDefinition candidate : candidates) {
			// 获取Bean定义类中@Scope注解的详细信息,即获取Bean的作用域
			ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
			// 设置这个BeanDefinition的Scope属性
			candidate.setScope(scopeMetadata.getScopeName());

			// 获取Bean的名字:有名字获取配置的名字,没有名字根据当前类进行获取:类名前俩位都大写,直接返回类名;前俩位不是大写,返回首字母小写的名称;
			String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

			// 给BeanDefinition赋一些默认值
			if (candidate instanceof AbstractBeanDefinition) {
				postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
			}
			// 解析@Lazy、@Primary、@DependsOn、@Role、@Description注解
			if (candidate instanceof AnnotatedBeanDefinition) {
				AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
			}

			// 检查Spring容器中是否已经存在该beanName
			if (checkCandidate(beanName, candidate)) {
				// 把BeanDefinition封装为BeanDefinitionHolder
				BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
				// 根据Scope的类型,来确认是否需要生产代理对象
				definitionHolder =
						AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
				beanDefinitions.add(definitionHolder);

				// 注册到beanDefinitionMap
				registerBeanDefinition(definitionHolder, this.registry);
			}
		}
	}
	// 返回所有的beanDefinition
	return beanDefinitions;
}

找到所有的BeanDefinition候选者: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);
	}
}

/**
 * 扫描包含Component注解的可成为Bean的方法
 */
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
	// 定义返回值的变量
	Set<BeanDefinition> candidates = new LinkedHashSet<>();
	try {
		// 获取basePackage下所有的文件资源:classpath*:com/cangqiong/**/*.class
		String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
				resolveBasePackage(basePackage) + '/' + this.resourcePattern;
		// 得到当前路径下的所有的文件资源。所有的编译后的class文件
		Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
		// 俩个日志的标记
		boolean traceEnabled = logger.isTraceEnabled();
		boolean debugEnabled = logger.isDebugEnabled();
		// 遍历每一个class文件
		for (Resource resource : resources) {
			// 日志打印
			if (traceEnabled) {
				logger.trace("Scanning " + resource);
			}
			// 当这个资源可读并且存在的时候
			if (resource.isReadable()) {
				try {
					// 得到当前资源的元数据,这里通过ASM(字节码直接解析)解析
					MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
					// excludeFilters、includeFilters判断,scan中配置的参数。
					if (isCandidateComponent(metadataReader)) { // @Component-->includeFilters判断
						// 构建扫描生成的BeanDefinition
						ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
						// 将当前的资源设置到读取好的元数据中
						sbd.setSource(resource);

						// 判断这个class:(他是顶级的类(不是内部类)或者他是静态内部类)并且 (不是接口不是抽象的 或者 他是抽象的并且有任意一个方法上有Lookup注解) 返回为true
						if (isCandidateComponent(sbd)) {
							if (debugEnabled) {
								logger.debug("Identified candidate component class: " + resource);
							}
							// 条件到BeanDefinition候选者中
							candidates.add(sbd);
						}
						else {
							// 无法添加当前类为bean的时候,打印日志
							if (debugEnabled) {
								logger.debug("Ignored because not a concrete top-level class: " + resource);
							}
						}
					}
					else {
						// 当前类不能成为bean,打印日志
						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;
}

/**
 * excludeFilters、includeFilters判断,scan中配置的参数。
 */
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
	// 满足excludeFilters的条件,直接返回false
	for (TypeFilter tf : this.excludeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return false;
		}
	}

	// 符合includeFilters的会进行条件匹配,通过了才是Bean,也就是先看有没有@Component,再看是否符合@Conditional。都满足后,今天条件匹配(继承condition类的方法)
	for (TypeFilter tf : this.includeFilters) {
		if (tf.match(metadataReader, getMetadataReaderFactory())) {
			return isConditionMatch(metadataReader);
		}
	}
	// 没有匹配上,返回false
	return false;
}

/**
 * 构建扫描生成的BeanDefinition
 */
public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
	// 非空判断,抛异常!
	Assert.notNull(metadataReader, "MetadataReader must not be null");
	// 得到元数据
	this.metadata = metadataReader.getAnnotationMetadata();
	// 这里只是把className设置到BeanDefinition中!!!!
	setBeanClassName(this.metadata.getClassName());
	// 设置resource
	setResource(metadataReader.getResource());
}

/**
 * 校验Bean是否之前存在
 */
protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
	// Bean之前不存在,直接返回true
	if (!this.registry.containsBeanDefinition(beanName)) {
		return true;
	}
	BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
	BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
	if (originatingDef != null) {
		existingDef = originatingDef;
	}
	// 是否兼容,如果兼容返回false(同一个类被重复扫描的时候)表示不会重新注册到Spring容器中,如果不兼容则会抛异常。
	if (isCompatible(beanDefinition, existingDef)) {
		return false;
	}

	// 不兼容的时候抛异常
	throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
			"' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
			"non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
}

结束语

  • 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
  • 关注公众号,可以让你对MySQL、并发编程、spring源码有深入的了解!
  • 关注公众号,后续持续高效的学习JVM!
  • 这个公众号,无广告!!!每日更新!!!
    作者公众号.jpg
posted @ 2022-02-22 23:40  程序java圈  阅读(192)  评论(0编辑  收藏  举报