Spring IOC:ComponentScanBeanDefinitionParser调用链

参考资料:

《Spring IoC源码学习:context:component-scan 节点详解》

前文:
 《Spring IOC:parseCustomElement调用链》

 写在开头:本文为个人学习笔记,内容比较随意,夹杂个人理解,如有错误,欢迎指正。

目录

一、parse

二、configureScanner

        1、configureScanner

        2、createScanner

        3、registerDefaultFilters

         4、parseTypeFilters

        5、createTypeFilter

三、doScan

        1、doScan

        2、 findCandidateComponents

        2.1、isCandidateComponent

         2.2、isCandidateComponent

        3、resolveScopeMetadata

        4、postProcessBeanDefinition

        5、processCommonDefinitionAnnotations

        6、checkCandidate

        7、applyScopedProxyMode

        8、registerBeanDefinition

三、registerComponents

        1、registerComponents

        2、registerAnnotationConfigProcessors

总结:


一、parse

        在前文中,我们了解到当 element 为 <context:component-scan /> 节点时,findParserForElement(element, parserContext) 会返回 ComponentScanBeanDefinitionParser,接着执行 ComponentScanBeanDefinitionParser类的parse 方法。

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 1.findParserForElement: 给element寻找对应的BeanDefinition解析器
    // 2.使用BeanDefinition解析器解析element节点
    return findParserForElement(element, parserContext).parse(element, parserContext);
}

         在parse方法中,我们首先解析base-package属性,拿到要扫描的路径,进行解析,如果有使用了占位符的还需要进行替换,如果有使用了分隔符","或者";"的,还需要拆分成数组。然后调用configureScanner方法构建ClassPathBeanDefinitionScanner来为后续扫描做准备。拿到ClassPathBeanDefinitionScanner后,调用其doScan方法,将扫描路径下使用了相关注解的类加入到beanDefinition中。最后,再注册其余的组件,如后置处理器等。

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
    // 拿到<context:component-scan>节点的base-package属性值
    String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
    // 解析占位符, 例如 ${basePackage}
    basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
    // 解析base-package(允许通过 ",; \t\n" 中的任一符号填写多个)
    // String CONFIG_LOCATION_DELIMITERS = ",; \t\n";
    String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
            ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
 
    // Actually scan for bean definitions and register them.
    // 构建和配置ClassPathBeanDefinitionScanner
    ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
    // 使用scanner在指定的basePackages包中执行扫描,返回已注册的bean定义
    Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
    // 组件注册(包括注册一些内部的注解后置处理器、触发注册事件)
    registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
 
    return null;
}

二、configureScanner

        1、configureScanner

        进入configureScanner方法,会先读取该节点下是否配置了use-default-filters属性,该属性用来指定是否使用默认的过滤器(注意是过滤器,不是过滤规则)。然后调用createScanner方法创建扫描器,创建完毕后,再解析一些其他属性,如resource-pattern、name-generator等。最后调用parseTypeFilters方法解析类型过滤器。

protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
    // 解析use-default-filters属性,默认为true,用于指示是否使用默认的filter
    boolean useDefaultFilters = true;
    if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
        useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
    }
 
    // Delegate bean definition registration to scanner class.
    // 构建ClassPathBeanDefinitionScanner,将bean定义注册委托给scanner类
    ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
    scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
    scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
 
    // 解析resource-pattern属性
    if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
        scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
    }
 
    try {
        // 解析name-generator属性
        parseBeanNameGenerator(element, scanner);
    }
    catch (Exception ex) {
        parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
    }
 
    try {
        // 解析scope-resolver、scoped-proxy属性
        parseScope(element, scanner);
    }
    catch (Exception ex) {
        parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
    }
 
    // 解析类型过滤器
    parseTypeFilters(element, scanner, parserContext);
 
    return scanner;
}

Spring IOC:ComponentScanBeanDefinitionParser调用链

        2、createScanner

        createScanner方法判断是否使用默认的filter,如果是,则继续调用registerDefaultFilters方法

protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
    return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
            readerContext.getEnvironment(), readerContext.getResourceLoader());
}
 
// ClassPathBeanDefinitionScanner.java
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
        Environment environment, ResourceLoader resourceLoader) {
 
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
 
    if (useDefaultFilters) {
        // 注册默认的filter
        registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}
 

        

        3、registerDefaultFilters

        registerDefaultFilters方法会将@Component和@ManagedBean对应的filter加入到includeFilters中。

// ClassPathScanningCandidateComponentProvider.java
protected void registerDefaultFilters() {
    // 添加@Component注解Filter到includeFilters中
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        // 添加@ManagedBean注解Filter到includeFilters中
        this.includeFilters.add(new AnnotationTypeFilter(
                ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
        logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
        // 添加@Named注解Filter到includeFilters中
        this.includeFilters.add(new AnnotationTypeFilter(
                ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
        logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}

         4、parseTypeFilters

        解析当前节点下的子节点,读取可能存在的include-filter和exclude-filter节点,然后针对读取到的属性调用createTypeFilter方法创建typeFilter,并加入到扫描器中。

protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
    // Parse exclude and include filter elements.
    ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
    NodeList nodeList = element.getChildNodes();
    // 遍历解析element下的所有子节点
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node node = nodeList.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            // 拿到节点的localName
            // 例如节点:<context:exclude-filter type="" expression=""/>,localName为:exclude-filter
            String localName = parserContext.getDelegate().getLocalName(node);
            try {
                /**
                 * 例如
                 * <context:component-scan base-package="com.joonwhee.open">
                 *     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
                 * </context:component-scan>
                 */
                // 解析include-filter子节点
                if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
                    // 构建TypeFilter
                    TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
                    // 添加到scanner的includeFilters属性
                    scanner.addIncludeFilter(typeFilter);
                }
                // 解析exclude-filter子节点
                else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
                    // 构建TypeFilter
                    TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
                    // 添加到scanner的excludeFilters属性
                    scanner.addExcludeFilter(typeFilter);
                }
            } catch (Exception ex) {
                parserContext.getReaderContext().error(
                        ex.getMessage(), parserContext.extractSource(element), ex.getCause());
            }
        }
    }
}
 

        5、createTypeFilter

        读取include-filter和exclude-filter节点中的type、expression属性,根据不同的属性创建AnnotationTypeFilter。比如type="annotation"时,表明按注解过滤,expression中设置注解的路径,如expression="org.springframework.stereotype.Controller",则会过滤掉@Controller注解。

protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) {
    // 获取type、expression
    String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
    String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
    expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);
    try {
        // 根据filterType,返回对应的TypeFilter,例如annotation返回AnnotationTypeFilter
        if ("annotation".equals(filterType)) {
            // 指定过滤的注解, expression为注解的类全名称, 例如: org.springframework.stereotype.Controller
            return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
        }
        else if ("assignable".equals(filterType)) {
            // 指定过滤的类或接口, 包括子类和子接口, expression为类全名称
            return new AssignableTypeFilter(classLoader.loadClass(expression));
        }
        else if ("aspectj".equals(filterType)) {
            // 指定aspectj表达式来过滤类, expression为aspectj表达式字符串
            return new AspectJTypeFilter(expression, classLoader);
        }
        else if ("regex".equals(filterType)) {
            // 通过正则表达式来过滤类, expression为正则表达式字符串
            return new RegexPatternTypeFilter(Pattern.compile(expression));
        }
        else if ("custom".equals(filterType)) {
            // 用户自定义过滤器类型, expression为自定义过滤器的类全名称
            Class<?> filterClass = classLoader.loadClass(expression);
            // 自定义的过滤器必须实现TypeFilter接口, 否则抛异常
            if (!TypeFilter.class.isAssignableFrom(filterClass)) {
                throw new IllegalArgumentException(
                        "Class is not assignable to [" + TypeFilter.class.getName() + "]: " + expression);
            }
            return (TypeFilter) BeanUtils.instantiateClass(filterClass);
        }
        else {
            throw new IllegalArgumentException("Unsupported filter type: " + filterType);
        }
    }
    catch (ClassNotFoundException ex) {
        throw new FatalBeanException("Type filter class not found: " + expression, ex);
    }
}

三、doScan

        1、doScan

        doScan方法会调用findCandidateComponents将符合要求的bean都找出来(即使用了注解,且满足filter过滤规则的bean)。遍历所有符合要求的bean,解析@Scope,生成beanName,然后调用postProcessBeanDefinition、processCommonDefinitionAnnotations进一步解析候选bean。后续再封装BeanDefinitionHolder,然后根据proxyMode的值选择是否创建作用域代理,最后注册BeanDefinition(即beanDefinitionMap、beanDefinitionNames、aliasMap这三个缓存)

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    // 遍历basePackages
    for (String basePackage : basePackages) {
        // 扫描basePackage,将符合要求的bean定义全部找出来(这边符合要求最常见的就是使用Component注解)
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        // 遍历所有候选的bean定义
        for (BeanDefinition candidate : candidates) {
            // 解析@Scope注解, 包括scopeName(默认为singleton,常见的还有prototype), 和proxyMode(默认不使用代理, 可选接口代理/类代理)
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            // 使用beanName生成器来生成beanName
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                // 进一步处理BeanDefinition对象,比如: 此bean是否可以自动装配到其他bean中
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 处理定义在目标类上的通用注解,包括@Lazy, @Primary, @DependsOn, @Role, @Description
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            // 检查beanName是否已经注册过,如果注册过,检查是否兼容
            if (checkCandidate(beanName, candidate)) {
                // 将当前遍历bean的 bean定义和beanName封装成BeanDefinitionHolder
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // 根据proxyMode的值(步骤4中解析), 选择是否创建作用域代理
                definitionHolder =
                        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 注册BeanDefinition(注册到beanDefinitionMap、beanDefinitionNames、aliasMap缓存)
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

 Spring IOC:ComponentScanBeanDefinitionParser调用链

        2、 findCandidateComponents

        读取配置的路径,将所有的类都加载进来,并使用过滤器检查给定的类是否为候选类,如满足要求,则加入到candidates中

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
    try {
        // 根据我们配置的包名,组装成要扫描的通配包路径,例如:com.joonwhee.open 会被组装成: classpath*:com/joonwhee/open/**/*.class
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        // 根据通配包路径匹配拿到所有匹配的类资源(本项目依赖的jar,如果路径也符合,则会一起扫描进来)
        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
        boolean traceEnabled = logger.isTraceEnabled();
        boolean debugEnabled = logger.isDebugEnabled();
        // 遍历所有匹配的类资源
        for (Resource resource : resources) {
            if (traceEnabled) {
                logger.trace("Scanning " + resource);
            }
            if (resource.isReadable()) {
                try {
                    // 使用metadataReader读取资源,MetadataReader是专门用来访问元数据的类(包括: 类元数据ClassMetadata、注解元数据AnnotationMetadata等)
                    MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                    // 使用过滤器检查给定的类是否为候选类(候选类: 与excludeFilters的所有Filter不匹配,并且与includeFilters的至少一个Filter匹配)
                    if (isCandidateComponent(metadataReader)) {
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        // 判断sbd是否为候选类(独立的 && (具体的实现类 || (抽象类 && 类中有方法使用@Lookup注解)))
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            // 确定是候选类,则添加到candidates
                            candidates.add(sbd);
                        }
                        else {
                            if (debugEnabled) {
                                logger.debug("Ignored because not a concrete top-level class: " + resource);
                            }
                        }
                    }
                    else {
                        if (traceEnabled) {
                            logger.trace("Ignored because not matching any filter: " + resource);
                        }
                    }
                }
                catch (Throwable ex) {
                    throw new BeanDefinitionStoreException(
                            "Failed to read candidate component class: " + resource, ex);
                }
            }
            else {
                if (traceEnabled) {
                    logger.trace("Ignored because not readable: " + resource);
                }
            }
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
    }
    return candidates;
}

Spring IOC:ComponentScanBeanDefinitionParser调用链

        2.1、isCandidateComponent

        判断metadataReader(MetadataReader是专门用来访问元数据的类)是否与excludeFilters 和 includeFilters中的TypeFilter相匹配。

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    for (TypeFilter tf : this.excludeFilters) {
        if (tf.match(metadataReader, this.metadataReaderFactory)) {
            // 如果metadataReader与excludeFilters中的任意一个匹配,则返回false,表示metadataReader对应的类不是候选者类
            return false;
        }
    }
 
    // includeFilters默认包含: org.springframework.stereotype.Component注解、javax.annotation.ManagedBean注解
    for (TypeFilter tf : this.includeFilters) {
        if (tf.match(metadataReader, this.metadataReaderFactory)) {
            // 如果metadataReader与includeFilters中的任意一个TypeFilter匹配(如果tf为Component注解:metadataReader对应的类使用了Component则匹配),
            // 则判断@Conditional注解是否匹配(@Conditional基本不用,此处不深入解析);如果匹配,则返回true,表示metadataReader对应的类为候选者类
            return isConditionMatch(metadataReader);
        }
    }
    return false;
}

Spring IOC:ComponentScanBeanDefinitionParser调用链

         2.2、isCandidateComponent

        继续判断该类是否满足要求。

protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
    AnnotationMetadata metadata = beanDefinition.getMetadata();
    // isIndependent:确定底层类是否是独立的,即它是否是*类或嵌套类(静态内部类),它可以独立于封闭类构造。
    // isConcrete:返回底层类是表示具体类,即:既不是接口也不是抽象类。
    // isAbstract:返回底层类是否标记为抽象。
    // hasAnnotatedMethods:确定基础类是否具有使用给定注解(@Lookup)类型进行注解(或元注解)的任何方法。
    return (metadata.isIndependent() && (metadata.isConcrete() ||
            (metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}

Spring IOC:ComponentScanBeanDefinitionParser调用链

        3、resolveScopeMetadata

        解析@Scope注解,判断是否使用代理模式。defaultProxyMode取决前文中parseScope方法读取到的scope-resolver、scoped-proxy属性,可以通过 scoped-proxy 来设置,默认为 ScopedProxyMode.NO。

@Override
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    ScopeMetadata metadata = new ScopeMetadata();
    if (definition instanceof AnnotatedBeanDefinition) {
        AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
                annDef.getMetadata(), this.scopeAnnotationType);
        // 如果使用了@Scope注解
        if (attributes != null) {
            // 解析scopeName属性
            metadata.setScopeName(attributes.getString("value"));
            // 解析proxyMode属性
            ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
            if (proxyMode == null || proxyMode == ScopedProxyMode.DEFAULT) {
                proxyMode = this.defaultProxyMode;
            }
            metadata.setScopedProxyMode(proxyMode);
        }
    }
    return metadata;
}

 

        4、postProcessBeanDefinition

        这一步给beanDefinition设置默认值,同时读取autowire-candidate,该属性用来设置某个bean是否在自动注入的时候是否为作为候选bean。

protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
    // 给beanDefinition设置默认值
    beanDefinition.applyDefaults(this.beanDefinitionDefaults);
    if (this.autowireCandidatePatterns != null) {
        // 设置此bean是否可以自动装配到其他bean中, 默认为true
        beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
    }
}
<bean id="beantest" class="com.test" autowire-candidate="false"/>

        5、processCommonDefinitionAnnotations

        继续解析常用属性,包括@Lazy, @Primary, @DependsOn, @Role, @Description。

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
 
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    // 解析@Lazy注解, 设置是否延迟加载
    if (metadata.isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
    }
 
    // 解析@Primary注解, 自动装配时当出现多个Bean都匹配时,被注解为@Primary的Bean将作为首选者,否则将抛出异常
    // (场景较小, 如果可能出现多个匹配者时, 可以使用@Autowired @Qualifier的组合)
    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }
    // 解析@DependOn注解
    if (metadata.isAnnotated(DependsOn.class.getName())) {
        abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
    }
 
    if (abd instanceof AbstractBeanDefinition) {
        // 解析@Role注解
        AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
        if (metadata.isAnnotated(Role.class.getName())) {
            absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
        }
        // 解析@Description注解
        if (metadata.isAnnotated(Description.class.getName())) {
            absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
        }
    }
}

        6、checkCandidate

        利用beanDefinitionMap判断该beanName是否已在缓存中,如不在,直接返回,如在,则取出该beanName在beanDefinitionMap中的BeanDefinition,继续判断,如使用了代理,则取出代理的BeanDefinition,并作为缓存中的值与当前要注册的BeanDefinition比较,判断是否兼容。

protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
    // 如果该注册表(beanDefinitionMap缓存)没有包含beanName, 则返回true,代表可以注册该bean定义
    if (!this.registry.containsBeanDefinition(beanName)) {
        return true;
    }
    // 如果注册表中包含beanName
    // 拿到注册表中该beanName的BeanDefinition
    BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
    // 拿到原始BeanDefinition(使用了代理的BeanDefinition会有原始BeanDefinition)
    BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
    if (originatingDef != null) {
        // 如果有原始BeanDefinition, 则使用原始BeanDefinition
        existingDef = originatingDef;
    }
    // 检查新BeanDefinition是否与原BeanDefinition兼容,如果兼容则返回false,跳过注册
    if (isCompatible(beanDefinition, existingDef)) {
        return false;
    }
    // 如果不兼容,则抛异常
    throw new ConflictingBeanDefinitionException("Annotation-specified bean name '" + beanName +
            "' for bean class [" + beanDefinition.getBeanClassName() + "] conflicts with existing, " +
            "non-compatible bean definition of same name and class [" + existingDef.getBeanClassName() + "]");
}

        7、applyScopedProxyMode

        判断是否使用代理模式,如是,则继续判断是基于接口还是基于类的代理,前者使用CGlib代理,后者使用JDK动态代理,确认代理模式后,创建相应的scope代理。

static BeanDefinitionHolder applyScopedProxyMode(
        ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
 
    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    // 如果不需要创建代理,则直接返回bean定义
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }
    // 判断是使用基于类的代理还是基于接口的代码, 基于类: 使用CGLIB代理, 基于接口: 使用JDK动态代理
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    // 使用相应的代理模式, 创建一个scope代理
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

 

        8、registerBeanDefinition

        调用 BeanDefinitionReaderUtils 工具类来完成 BeanDefinition 的注册。此方法在默认命名空间节点解析中已介绍过(《Spring IOC:parseDefaultElement调用链》第5小节),这里不再赘述,主要作用在于注册beanDefinitionMap、beanDefinitionNames、aliasMap这三个缓存。

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    // 调用BeanDefinitionReaderUtils工具类来完成BeanDefinition的注册
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}

三、registerComponents

        1、registerComponents

        判断是否需要注册基于注解的bean后置处理器,默认为treu,然后调用registerAnnotationConfigProcessors方法进行注册。

protected void registerComponents(
        XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
 
    Object source = readerContext.extractSource(element);
    // 使用注解的tagName(例如: context:component-scan)和source 构建CompositeComponentDefinition
    CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
 
    // 将扫描到的所有BeanDefinition添加到compositeDef的nestedComponents属性中
    for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
        compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
    }
 
    boolean annotationConfig = true;
    if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
        // 获取component-scan标签的annotation-config属性值(默认为true)
        annotationConfig = Boolean.valueOf(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
    }
    if (annotationConfig) {
        // 如果annotation-config属性值为true,在给定的注册表中注册所有用于注解的Bean后置处理器
        Set<BeanDefinitionHolder> processorDefinitions =
                AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
        for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
            // 将注册的注解后置处理器的BeanDefinition添加到compositeDef的nestedComponents属性中
            compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
        }
    }
 
    // 触发组件注册事件,默认实现为EmptyReaderEventListener(空实现,没有具体操作)
    readerContext.fireComponentRegistered(compositeDef);
}

 

        2、registerAnnotationConfigProcessors

        判断是否包含常用注解的BeanDefinition,包括@Configuration、@Autowired、@Required、@Resource等基于后置处理器实现的注解,然后调用registerPostProcessor注册。

        核心注册方法registerBeanDefinition 在《Spring IOC:parseDefaultElement调用链》中第5小节已分析过,这里省略。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, Object source) {
 
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 设置dependencyComparator属性
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // 设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }
 
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
 
    // 注册内部管理的用于处理@Configuration注解的后置处理器的bean
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        // registerPostProcessor: 注册BeanDefinition到注册表中
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
 
    // 注册内部管理的用于处理@Autowired、@Value、@Inject以及@Lookup注解的后置处理器的bean
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
 
    // 注册内部管理的用于处理@Required注解的后置处理器的bean
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
 
    // 注册内部管理的用于处理JSR-250注解(例如@Resource, @PostConstruct, @PreDestroy)的后置处理器的bean
    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
 
    // 注册内部管理的用于处理JPA注解的后置处理器的bean
    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                    AnnotationConfigUtils.class.getClassLoader()));
        } catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
 
    // 注册内部管理的用于处理@EventListener注解的后置处理器的bean
    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }
    // 注册内部管理用于生产ApplicationListener对象的EventListenerFactory对象
    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }
 
    return beanDefs;
}

private static BeanDefinitionHolder registerPostProcessor(
        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
 
    // 设置role
    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    // 注册BeanDefinition
    registry.registerBeanDefinition(beanName, definition);
    // 封装成BeanDefinitionHolder并返回
    return new BeanDefinitionHolder(definition, beanName);
}

 

总结:

        <context:component-scan> 节点解析过程主要分为以下几步:

        1、扫描 base-package 目录,将所有基于@Component注解的bean取出,并加入到注册表中(依然是这三个重要缓存中,beanDefinitionMap、beanDefinitionNames、aliasMap,和前文parseDefaultElement调用链解析默认命名空间一样)

        2、将几个常规的bean后置处理器加入到BeanDefinition中,比如@Autowired所基于的AutowiredAnnotationBeanPostProcessor等。

        

上一篇:我的Android进阶之旅------>Android自定义窗口标题实例


下一篇:Spring面试常问