Spring生命周期图解
Bean在启动前期会先扫描包路径然后生成BeanDefintion,先看看下Spring扫描的底层实现(扫描流程图见文章最下方):
Spring源码ClassPathBeanDefintionScanner#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);
省略
.................................
}
首先是迭代basePackages(扫包路径com.xxx) 进入到第一个方法 findCandidateComponents
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
return scanCandidateComponents(basePackage);
}
}
这个方法有两个分支 A分支代表了指定了Bean B分支是我们平时用的扫描模式,在这里我们也只看B分支 ClassPathScanningCandidateComponentProvider#scanCandidateComponents
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
// 获取basePackage下所有的文件资源
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);
// 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;
}
这个方法干的事情就是:
- 首先,通过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加入结果集 简单来讲就是扫描指定包下类,找到符合规则的(带有@Component注解并且对应的类不是接口和抽象类没有被过滤排除,在有条件注解的情况下满足条件)转换成BeanDefintion加入候选BeanDefintion集合
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) {
//刚刚拿到的候选BeanDefintion
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
//获取BeanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
//设置BeanDefinition的默认值
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;
}
- 遍历刚刚的候选BeanDefintion。
- 获取BeanDefintion元数据同时设置默认的Scope为单例。
- 获取BeanName 这里要看注解是否指定了beanName,指定则使用指定的beanName,不指定则使用当前类目小写首字母作为BeanName。
- 设置BeanDefinition的默认值。
- 解析BeanDefinition对应类上是否存在@Lazy、@Primary、@DependsOn、@Role、@Description 注解,存在则标记到BeanDefinition中去。
- 检查Spring容器中是否已经存在该beanName 这里要看是否兼容,如果不兼容则抛出异常说明BeanName已存在,兼容的情况是在有多个扫包路径扫到同一个类的情况下。
- 生成BeanDefinitionHolder存入集合中,BeanDefinitionHolder顾名思义就是对BeanDefinition的持有,同时持有的包括BeanDefinition的名称和别名。
- 注册,要判断当前BeanName是否在Spring容器中存在,如果不存在则把BeanName以及BeanDefinition注册到map中,如果存在则报错。