componet-scan

分为 xml 配置 和 注解配置两种方式,二者入口不同,实现上没太多差别.
都是先解析配置,根据配置的 basePackages 用asm扫描.class上是否有@Component注解,若有则生成beanName,注册到容器里即可.

context:component-scan/实现

配置

1
<context:component-scan base-package="com.zc"/>

切入点

对于自定义标签的解析入口在 DefaultBeanDefinitionDocumentReader.parseCustomElement(ele); 里.
1.先根据标签获取parser,这里是 ComponentScanBeanDefinitionParser
根据标签获取parser

调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- NamespaceHandlerSupport.parse(): 根据元素获取parser进行处理,这里使用的是ComponentScanBeanDefinitionParser
- ComponentScanBeanDefinitionParser.parse()
- 1.configureScanner()
- ComponentScanBeanDefinitionParser.createScanner()
- 1.createScanner(): 将 beanDefinition注册 委托给 Scanner 类
- ClassPathScanningCandidateComponentProvider()构造方法
- 1.registerDefaultFilters(): 支持Component注解,创建AnnotationTypeFilter,加入includeFilters里
- 2.parseBeanNameGenerator(): 生成beanName
- 3.parseScope(): 解析 scoped-proxy 和 scope-resolver 属性
- 4.parseTypeFilters(): 解析配置的类型过滤器属性,包括 include-filter 和 exclude-filter
- 2.scanner.doScan(basePackages)
- ComponentScanBeanDefinitionParser.doScan()
- 1.遍历所有basePackage
- 2.findCandidateComponents(basePackage): 扫描 basePackage 下的 bean definition
- ClassPathScanningCandidateComponentProvider.findCandidateComponents()
- 1.根据 basePackage 从 classpath*:com/zc/**/*.class 中 扫描所有符合条件的 .class
- 2.遍历符合条件的.class,用asm判断上面是否有 @Component 注解
- 3.遍历 上一步扫出来的@Component注解的beanDefinitions,生成beanName
- AnnotationBeanNameGenerator.generateBeanName()
- 1.determineBeanNameFromAnnotation(): 若注解上配了value值,作为beanName
- 2.若没配置,则buildDefaultBeanName()获取类名转成对象名,返回默认的beanName
- 4.若beanDefinition没注册,调用registerBeanDefinition()注册beanDefinition

@ComponentScan 注解实现

入口再 ComponentScanAnnotationParser 里,实现上和上面差不多.