Spring源码之Bean组件扫描解析类ClassPathBeanDefinitionScanner
1.前言
在Spring的使用中,我没会通过@Controller、@Service、@Repository、@Component组件标注在一个类上,告诉Spring此类为一个Bean组件类,交由Spring为我们创建类的实例和管理Bean组件相关的生命周期。
Spring管理Bean组件大致分为两大阶段。
第一阶段(解析):是将我们通过组件注解标注的类解析成Bean组件的定义对象,也就是对应的BeanDefinition对象,该对象用来描述每个组件的一些基本信息
第二阶段(创建):获取所有解析后的BeanDefinition对象,根据其相关属性创建成最终的一个个实例对象,实例的创建过程也会出发组件生命周期相关的勾子函数
2.准备工作
Spring版本:2.2.13.RELEASE
说明:文中统一将被@Controller、@Service、@Repository、@Component标注的类称为组件类
源码中涉及的类
- ClassPathBeanDefinitionScanner
- ClassPathScanningCandidateComponentProvider
3.源码流程分析
3.1流程入口方法 ClassPathBeanDefinitionScanner.scan
public int scan(String... basePackages) { // 获取此次组件扫描之前Spring容器中组件定义的数量 int beanCountAtScanStart = this.registry.getBeanDefinitionCount(); // 根据包路径开始扫描包下的所有组件 doScan(basePackages); // 是否开启注解驱动,主要针对@Autowird、@Configuration、@PostConstruct、@PreDestroy等注解的支持 if (this.includeAnnotationConfig) { AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry); } // 返回此次扫描新增的组件数量 return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart); }
3.2 ClassPathBeanDefinitionScanner.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) { /* 解析组件的作用域 singleton、prototype、request、session、global */ 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) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); } // 检查是否为候选的组件,如果是则将该组件的定义信息注册到Spring容器中 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; }
3.3ClassPathScanningCandidateComponentProvider.findCandidateComponents
public Set<BeanDefinition> findCandidateComponents(String basePackage) { // 针对组件上的@Index注解的处理逻辑 if (this.componentsIndex != null && indexSupportsIncludeFilters()) { return addCandidateComponentsFromIndex(this.componentsIndex, basePackage); } else { return scanCandidateComponents(basePackage); } } private Set<BeanDefinition> scanCandidateComponents(String basePackage) { // 组件定义集合,也是该方法的返回值 Set<BeanDefinition> candidates = new LinkedHashSet<>(); try { // 根据包路劲封装成Ant风格的全路径名称 org.spring -> classpath*:org/spring/**/*.class String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern; // 调用资源模式解析器解析该路径下的所有类资源,这里的资源模式解析器用的是PathMatchingResourcePatternResolver,支持Ant路径模式 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); boolean traceEnabled = logger.isTraceEnabled(); boolean debugEnabled = logger.isDebugEnabled(); // 循环每一个类资源处理 for (Resource resource : resources) { if (traceEnabled) { logger.trace("Scanning " + resource); } try { // 获取类资源上的元数据读取者 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); // 是否为候选的组件,通过TypeFilter进行包含和排除过滤 if (isCandidateComponent(metadataReader)) { // 封装成组件定义类BeanDefinition ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); 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 (FileNotFoundException ex) { if (traceEnabled) { logger.trace("Ignored non-readable " + resource + ": " + ex.getMessage()); } } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to read candidate component class: " + resource, ex); } } } catch (IOException ex) { throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); } return candidates; }
3.4AnnotationConfigUtils.processCommonDefinitionAnnotations
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) { /* 处理@Lazy、@Primary、@DependsOn、@Role、@Description注解 */ 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")); } } if (metadata.isAnnotated(Primary.class.getName())) { abd.setPrimary(true); } AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class); if (dependsOn != null) { abd.setDependsOn(dependsOn.getStringArray("value")); } AnnotationAttributes role = attributesFor(metadata, Role.class); if (role != null) { abd.setRole(role.getNumber("value").intValue()); } AnnotationAttributes description = attributesFor(metadata, Description.class); if (description != null) { abd.setDescription(description.getString("value")); } }