開(kāi)篇
?在Spring 加載BeanDefinition的這篇文章中我們著重分析了BeanDefinition的加載過(guò)程并提到了對(duì)于<component-scan>標(biāo)簽的解析,這篇文章我們深入細(xì)化下Spring針對(duì)如@Component注解的加載過(guò)程妹窖。
?整個(gè)流程核心在于1、解析basePackage的路徑个绍;2勒葱、掃描basePackage路徑查找class文件;3巴柿、判斷是否符合過(guò)濾條件凛虽,經(jīng)過(guò)上述3個(gè)步驟后返回符合要求的BeanDefinition對(duì)象。
Component-scan流程分析
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
}
}
說(shuō)明:
- 1广恢、注冊(cè)component-scan對(duì)應(yīng)的解析器ComponentScanBeanDefinitionParser凯旋。
public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";
private static final String RESOURCE_PATTERN_ATTRIBUTE = "resource-pattern";
private static final String USE_DEFAULT_FILTERS_ATTRIBUTE = "use-default-filters";
private static final String ANNOTATION_CONFIG_ATTRIBUTE = "annotation-config";
private static final String NAME_GENERATOR_ATTRIBUTE = "name-generator";
private static final String SCOPE_RESOLVER_ATTRIBUTE = "scope-resolver";
private static final String SCOPED_PROXY_ATTRIBUTE = "scoped-proxy";
private static final String EXCLUDE_FILTER_ELEMENT = "exclude-filter";
private static final String INCLUDE_FILTER_ELEMENT = "include-filter";
private static final String FILTER_TYPE_ATTRIBUTE = "type";
private static final String FILTER_EXPRESSION_ATTRIBUTE = "expression";
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 獲取base-package路徑
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// 針對(duì)base-package的路徑進(jìn)行掃描
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 注冊(cè)BeanDefinition對(duì)象
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
}
說(shuō)明:
- 2、創(chuàng)建ClassPathBeanDefinitionScanner類型的scanner對(duì)象钉迷。
- 3至非、通過(guò) scanner.doScan()掃描符合base_package的class文件。
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 根據(jù)basePackage去查找
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) {
// 組裝BeanDefinition默認(rèn)屬性
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 解析類中的注解配置
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
// 檢查符合條件的BeanDefinition并注冊(cè)
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;
}
}
說(shuō)明:
- 4糠聪、findCandidateComponents方法負(fù)責(zé)查找候選集荒椭,內(nèi)部繼續(xù)跟進(jìn)查看。
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
}
else {
// 暫時(shí)關(guān)注這部分邏輯
return scanCandidateComponents(basePackage);
}
}
}
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
Set<BeanDefinition> candidates = new LinkedHashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 真正執(zhí)行查找的邏輯舰蟆,class文件查找的實(shí)現(xiàn)細(xì)節(jié)
Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
for (Resource resource : resources) {
if (resource.isReadable()) {
try {
MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
// 判斷是否符合候選集趣惠,核心的判斷在于isCandidateComponent
if (isCandidateComponent(metadataReader)) {
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
if (isCandidateComponent(sbd)) {
candidates.add(sbd);
}
}
}
catch (Throwable ex) {
}
}
}
}
catch (IOException ex) {
}
return candidates;
}
}
說(shuō)明:
- 5、getResourcePatternResolver().getResources(packageSearchPath)負(fù)責(zé)查找對(duì)象身害,內(nèi)部針對(duì)文件味悄、jar包等多種數(shù)據(jù)結(jié)構(gòu)進(jìn)行查找,細(xì)節(jié)可以深究一下塌鸯。
- 6侍瑟、通過(guò)isCandidateComponent()判斷是否是候選集對(duì)象。
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, getMetadataReaderFactory())) {
return isConditionMatch(metadataReader);
}
}
return false;
}
}
public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
}
- 7界赔、isCandidateComponent先經(jīng)過(guò)excludeFilters進(jìn)行過(guò)濾丢习,在經(jīng)過(guò)includeFilters過(guò)濾,最后返回是否符合淮悼。
- 8、includeFilters通過(guò)registerDefaultFilters注冊(cè)過(guò)濾器揽思,默認(rèn)我們發(fā)現(xiàn)有Componet注解袜腥。