Spring component-scan 实现原理

componet-scan

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

context:component-scan/实现

配置

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

切入点

对于自定义标签的解析入口在 DefaultBeanDefinitionDocumentReader.parseCustomElement(ele); 里.
1.先根据标签获取parser,这里是 ComponentScanBeanDefinitionParser
Spring component-scan 实现原理_第1张图片

调用

- 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 里,实现上和上面差不多.

你可能感兴趣的:(Spring)