Spring是如何自动装配Bean的?看源码+一些自己的理解,如有错漏,请指正
使用Spring之前我们要先去web.xml中设置一下Spring的配置文件,在Spring的配置文件中,是通过component-scan
扫描器去扫描base-package
底下所有的类装配到容器中。
<context:component-scan base-package="xxx"/>
要怎么看component-scan的处理类呢?这要看在这个配置文件顶部配置的context命名空间。
xmlns:context="http://www.springframework.org/schema/context"
然后根据这个命名空间去context对应的jar包中找到spring.handlers
,在这个文件中就可以找到
点进去后就可以看到对应的处理类
再点进来,就可以看到最主要的方法:parse(Element element, ParserContext parserContext)
public BeanDefinition parse(Element element, ParserContext parserContext) {
StringbasePackage = element.getAttribute("base-package");
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ",; \t\n");
//配置扫描器
ClassPathBeanDefinitionScanner scanner = this.configureScanner(parserContext, element);
//扫描basePackages,将BeanDefinition装配到容器中
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
this.registerComponents(parserContext.getReaderContext(), beanDefinitions, element);//将组成部分进行注册(这边没什么用处,只是用于扩展)
return null;
}
先来看看doScan
方法
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet();
String[] var3 = basePackages;
int var4 = basePackages.length;
for(int var5 = 0; var5 < var4; ++var5) {
String basePackage = var3[var5];
Set<BeanDefinition> candidates = this.findCandidateComponents(basePackage);
Iterator var8 = candidates.iterator();
while(var8.hasNext()) {
BeanDefinition candidate = (BeanDefinition)var8.next();
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);//
candidate.setScope(scopeMetadata.getScopeName());
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
if (candidate instanceof AbstractBeanDefinition) {
this.postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
}
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
}
if (this.checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
this.registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
这个方法中最重要的就是this.registerBeanDefinition(definitionHolder, this.registry)
这句代码,跟着代码走到最后,发现最终是将对应的beanDefinition放到了ConcurrentHashMap中,实现了Bean的装配。
this.beanDefinitionMap.put(beanName, beanDefinition);
这自动装配的逻辑过得有点快,不管了,先这样。