Spring生命周期 (1)扫描类文件生成bean定义

Spring生命周期 (1)扫描类文件生成bean定义

​ bean的生命周期简略来看可以分为实例化前、实例化、实例化后、初始化前、初始化、初始化后。

​ 详细来看可以是

  1. 扫描类文件生成bean定义
  2. 合并beandefinion
  3. 实例化前
  4. 推断构造方法
  5. 实例化
  6. beandefinition后置处理
  7. 填充属性
  8. 执行aware
  9. 初始化前
  10. 初始化
  11. 初始化后

接下来从源码挨个解析该过程

1 扫描扫描类文件生成bean定义

1 传递扫描包,根据扫描路径把对应的bean定义保存到map中

public int scan(String... basePackages) {
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
		doScan(basePackages);
		// Register annotation config processors, if necessary.
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}
		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}
1.1 获取bean定义的数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
1.2 开始扫描 也就是doscan方法
	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);
			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) {
					// 解析@Lazy、@Primary、@DependsOn、@Role、@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 检查Spring容器中是否已经存在该beanName
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					// 注册
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

public class BeanDefinitionHolder implements BeanMetadataElement {

	private final BeanDefinition beanDefinition;

	private final String beanName;

	@Nullable
	private final String[] aliases;
}

​ 然后开始循环遍历给的路径,每个路径经过的方法是一样的,首先

​ Set candidates = findCandidateComponents(basePackage);这个方法的作用是扫描这些路径下的类,然后判断是否能转化成bean定义

1.3 scanCandidateComponents方法

​ findCandidateComponents然后会调用scanCandidateComponents(basePackage);这个方法,这个方法就是扫描的主要逻辑

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
		Set<BeanDefinition> candidates = new LinkedHashSet<>();
		try {
			// 获取basePackage下所有的文件资源
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            //Spring的方法 可以把class文件转化成资源
			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 {
                        //使用了asm框架读取class的元数据 
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
						// excludeFilters、includeFilters判断 
						if (isCandidateComponent(metadataReader)) { // @Component-->includeFilters判断
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setSource(resource);
							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;
	}

isCandidateComponent(metadataReader)方法会把需要排除的类和需要添加的类装进两个List里面也就是

private final List<TypeFilter> includeFilters = new ArrayList<>();

private final List<TypeFilter> excludeFilters = new ArrayList<>();

excludeFilters是排除,当在这个里面的时候就算类可以创建成bean也不进行转化,可以在ComponentScan中添加排除一部分类。includeFilters是进行添加的 其中@Component就是在这个里面判断的。

​ 其中 判断是否符合includeFilters之后进行了一个isConditionMatch(metadataReader);的方法,这个方法其实就是@Conditional注解的判断,也就是说这块先进行判断如果在excludeFilters里面直接返回false,然后不进行创建bean定义,再判断是否有includeFilters的注解啥的,如果有再进行判断Conditional注解,相关源码

​ 匹配的源码 ,其中Conditional注解在isConditionMatch(metadataReader);中。

/**
	 * 确定给定类是否与任何排除筛选器匹配,而与至少一个包含筛选器匹配.
	 *
	 * @param metadataReader the ASM ClassReader for the class
	 * @return whether the class qualifies as a candidate component
	 */
	protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
		for (TypeFilter tf : this.excludeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return false;
			}
		}

		// 符合includeFilters的会进行条件匹配,通过了才是Bean,也就是先看有没有@Component,再看是否符合@Conditional
		for (TypeFilter tf : this.includeFilters) {
			if (tf.match(metadataReader, getMetadataReaderFactory())) {
				return isConditionMatch(metadataReader);
			}
		}
		return false;
	}

​ isConditionMatch方法接下来的调用

/**
 *根据任何{@code @Conditional}注释确定给定的类是否是候选组件。
 *
 * @param metadataReader the ASM ClassReader for the class
 * @return whether the class qualifies as a candidate component
 */
private boolean isConditionMatch(MetadataReader metadataReader) {
   if (this.conditionEvaluator == null) {
      this.conditionEvaluator =
            new ConditionEvaluator(getRegistry(), this.environment, this.resourcePatternResolver);
   }
   return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}

shouldSkip的调用

/**
 * 根据{@code @Conditional}注释确定一个项目是否应该被跳过。
 * @param metadata the meta data
 * @param phase the phase of the call
 * @return if the item should be skipped
 */
public boolean shouldSkip(@Nullable AnnotatedTypeMetadata metadata, @Nullable ConfigurationPhase phase) {
   if (metadata == null || !metadata.isAnnotated(Conditional.class.getName())) {
      return false;
   }

   if (phase == null) {
      if (metadata instanceof AnnotationMetadata &&
            ConfigurationClassUtils.isConfigurationCandidate((AnnotationMetadata) metadata)) {
         return shouldSkip(metadata, ConfigurationPhase.PARSE_CONFIGURATION);
      }
      return shouldSkip(metadata, ConfigurationPhase.REGISTER_BEAN);
   }

   List<Condition> conditions = new ArrayList<>();
   for (String[] conditionClasses : getConditionClasses(metadata)) {
      for (String conditionClass : conditionClasses) {
         Condition condition = getCondition(conditionClass, this.context.getClassLoader());
         conditions.add(condition);
      }
   }

   AnnotationAwareOrderComparator.sort(conditions);

   for (Condition condition : conditions) {
      ConfigurationPhase requiredPhase = null;
      if (condition instanceof ConfigurationCondition) {
         requiredPhase = ((ConfigurationCondition) condition).getConfigurationPhase();
      }
       //condition的匹配方法
      if ((requiredPhase == null || requiredPhase == phase) && !condition.matches(this.context, metadata)) {
         return true;
      }
   }

   return false;
}

我理解的这个方法的大概意义在于判断一个类是否要添加成一个bean定义,比如判断是否是抽象类,抽象类的情况处理等。

接下来返回scanCandidateComponents方法,当判断完一个类是否能转化成bean定义之后,把元数据转化成一个bean定义,

ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setSource(resource);

如果这个bean定义是一个顶级类或者不是抽象类的判断 也是bean定义是否正常的判断。

protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
   AnnotationMetadata metadata = beanDefinition.getMetadata();
   return (metadata.isIndependent() && (metadata.isConcrete() ||
         (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}

如果正常 返回回去存储进set返回回去。

Set<BeanDefinition> candidates = new LinkedHashSet<>();

然后返回到doscan方法,获取到了bean定义。

循环bean定义的方法再次摘抄出来 ,一行一行解析。

for (BeanDefinition candidate : candidates) {
    //转化成注解元数据,可以使用工具类直接获取
   ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
   candidate.setScope(scopeMetadata.getScopeName());
    //推断beanname,判断bean名称应该是什么  注解中有按照注解 没有按照大小写生成。
   String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
    //如果bean定义是抽象的 则设置一些默认属性。
   if (candidate instanceof AbstractBeanDefinition) {
      postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
   }
    //解析各种注解,存入bean定义中
   if (candidate instanceof AnnotatedBeanDefinition) {
      // 解析@Lazy、@Primary、@DependsOn、@Role、@Description
      AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
   }
   // 检查Spring容器中是否已经存在该beanName
   if (checkCandidate(beanName, candidate)) {
      BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
      definitionHolder =
            AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
      beanDefinitions.add(definitionHolder);
      // 注册 其实是保存进一个map中。
      registerBeanDefinition(definitionHolder, this.registry);
   }
}

到此为止 扫描的过程结束。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值