spring提供自动扫描功能的核心类是:ClassPathBeanDefinitionScanner
该类根据提供个基础包名,扫描classpath下该包名的路径下,找到符合条件的类并注册到容器中。
默认情况下,ClassPathBeanDefinitionScanner将会扫面所有用Spring指定了的注解标识了的类,包括:@Component。也可以对扫描的机制进行配置,设置一些Filter,只有满足Filter的类才能被注册为Bean。
ClassPathBeanDefinitionScanner(子类)类主要完成扫描加载依赖组件的初始化以及将BeanDefinition注册到registry。
ClassPathScanningCandidateComponentProvider(其父类)主要完成包扫描以及BeanDefinition加载。
- <context:component-scan>背后是ComponentScanBeanDefinitionParser在工作
- ComponentScanBeanDefinitionParser背后依然是委托给ClassPathBeanDefinitionScanner扫描注册。
<context:component-scan base-package="com.xxx">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
//ComponentScanBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// Actually scan for bean definitions and register them.
//创建scanner 扫描注册bean definitions
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}
源码解析
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
//bean定义的注册器接口,用于注册BeanDefinition
private final BeanDefinitionRegistry registry;
private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();
@Nullable
private String[] autowireCandidatePatterns;
// bean的名称生成器
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
private boolean includeAnnotationConfig = true;
/**
* 构造函数,创建ClassPathBeanDefinitionScanner扫描器,同时根据参数设置filter以及resourceLoader
* @since 4.3.6
*/
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, @Nullable ResourceLoader resourceLoader) {
this.registry = registry;
if (useDefaultFilters) {
//设置Filter
registerDefaultFilters();
}
//设置environment
setEnvironment(environment);
//设置resourceLoader
setResourceLoader(resourceLoader);
}
/**
* 扫描给定的包路径,生成BeanDefinition并注册到注册器
*/
public int scan(String... basePackages) {
//获取注册器中已注册的bean数量
int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
//通过doScan给定包路径并生成BeanDefinition注册到registry中
doScan(basePackages);
if (this.includeAnnotationConfig) {
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
/**
* 扫描给定的包路径,生成BeanDefinition并注册到注册器
*/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
//遍历给定扫描的包
for (String basePackage : basePackages) {
// 调用findCandidateComponents扫描包组装BeanDefinition集合
//findCandidateComponents方法为父类方法
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
//遍历BeanDefinition,根据条件将BeanDefinition注册到注册中心
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) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
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;
}
}