@ComponentScan
需要了解BeanFactoryPostProcessor的基本知识,知道BeanFactoryPostProcessor在Spring中什么时候被调用。
简单示例
当在启动类上加上@ComponentScan指定路径后就可以把路径下的相关类注册成Bean了
@ComponentScan(value = "org.geekbang.thinking.in.spring.annotation.component")
public class ComponentScanDemo {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册 Configuration Class
context.register(ComponentScanDemo.class);
// 启动 Spring 应用上下文
context.refresh();
// 依赖查找 TestClass Bean
TestClass testClass = context.getBean(TestClass.class);
// Annotation -> AnnotationAttributes(Map)
System.out.println(testClass);
// 关闭 Spring 应用上下文
context.close();
}
}
处理过程
在spring中,一般对注解处理的都在ConfigurationClassPostProcessor#processConfigBeanDefinitions中,在第318行
// 配置类解析
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
// 解析注册类,例如(ComponentScanDemo.class)
parser.parse(candidates);
parser.validate();
来到ConfigurationClassParser#doProcessConfigurationClass方法中的283行,可以看到ComponentScan.class的身影
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan