美文网首页
Spring源码解析-业务Bean扫描

Spring源码解析-业务Bean扫描

作者: engineer_tang | 来源:发表于2020-08-31 07:53 被阅读0次

    1. 简介

    @Controller、@Service、@Repository都继承了@Component的特性,所以它们能够被Spring容器扫描,放入容器中。如下以Controller注解源码为例

    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Component
    public @interface Controller {
    
        /**
         * The value may indicate a suggestion for a logical component name,
         * to be turned into a Spring bean in case of an autodetected component.
         * @return the suggested component name, if any (or empty String otherwise)
         */
        @AliasFor(annotation = Component.class)
        String value() default "";
    
    }
    

    2. ClassPathScanningCandidateComponentProvider类

    2.1 ClassPathBeanDefinitionScanner类

    image.png

    在指定的基本包中执行扫描,返回注册的bean定义。

        /**
         * Perform a scan within the specified base packages,
         * returning the registered bean definitions.
         * <p>This method does <i>not</i> register an annotation config processor
         * but rather leaves this up to the caller.
         * @param basePackages the packages to check for annotated classes
         * @return set of beans registered if any for tooling registration purposes (never {@code null})
         */
        protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
            Assert.notEmpty(basePackages, "At least one base package must be specified");
            Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
            for (String basePackage : basePackages) {
                Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
                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;
        }
    

    2.2 AnnotationTypeFilter过滤器

    这个过滤器在spring-core的包下

    继承关系如下

    image.png
    2.3 ClassPathScanningCandidateComponentProvider类
    确定给定的类是否与任何排除筛选器不匹配,并且至少匹配一个include过滤器
        /**
         * Determine whether the given class does not match any exclude filter
         * and does match at least one include filter.
         * @param metadataReader the ASM ClassReader for the class
         * @return whether the class qualifies as a candidate component
         */
        protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
            for (TypeFilter tf : this.excludeFilters) {
                if (tf.match(metadataReader, getMetadataReaderFactory())) {
                    return false;
                }
            }
            for (TypeFilter tf : this.includeFilters) {
                if (tf.match(metadataReader, getMetadataReaderFactory())) {
                    return isConditionMatch(metadataReader);
                }
            }
            return false;
        }
    

    寻找组件

        /**
         * Scan the class path for candidate components.
         * @param basePackage the package to check for annotated classes
         * @return a corresponding Set of autodetected bean definitions
         */
        public Set<BeanDefinition> findCandidateComponents(String basePackage) {
            if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
                return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
            }
            else {
                return scanCandidateComponents(basePackage);
            }
        }
    

    相关文章

      网友评论

          本文标题:Spring源码解析-业务Bean扫描

          本文链接:https://www.haomeiwen.com/subject/yxoesktx.html