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

简介: 在 Spring IoC:parseCustomElement详解 中,我们介绍了自定义命名空间节点解析的大部分内容,但是还剩下节点解析的具体过程。本文将以<context:component-scan /> 节点为例子,介绍自定义命名空间 context 的 component-scan 节点的解析过程。

目录

Spring IoC源码学习全系列

前言

正文

ComponentScanBeanDefinitionParser.parse

代码块1configureScanner

代码块2createScanner

代码块3registerDefaultFilters

代码块4parseTypeFilters

代码块5doScan

代码块6findCandidateComponents

代码块7isCandidateComponent

代码块8isCandidateComponent

代码块9resolveScopeMetadata

代码块10postProcessBeanDefinition

代码块11processCommonDefinitionAnnotations

代码块12checkCandidate

代码块13applyScopedProxyMode

代码块14createScopedProxy

代码块15registerBeanDefinition

代码块16registerComponents

代码块17registerAnnotationConfigProcessors

代码块18registerPostProcessor

总结

相关文章


Spring IoC源码学习全系列

小白也看得懂的 Spring IoC 核心流程介绍

Spring IoC源码学习:总览

Spring IoC源码学习ApplicationContext 刷新前的配置

Spring IoC源码学习obtainFreshBeanFactory详解

Spring IoC源码学习parseDefaultElement详解

Spring IoC源码学习parseCustomElement详解

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

Spring IoC源码学习invokeBeanFactoryPostProcessors详解

Spring IoC源码学习registerBeanPostProcessors详解

Spring IoC源码学习finishBeanFactoryInitialization详解

Spring IoC源码学习getBean详解

Spring IoC源码学习createBean详解(上)

Spring IoC码学习createBean详解(下)

Spring IoC源码学习:@Autowire详解

Spring IoC源码学习:finishRefresh详解

 

前言


Spring IoCparseCustomElement详解中,我们介绍了自定义命名空间节点解析的大部分内容,但是还剩下节点解析的具体过程。本文将以<context:component-scan /> 节点为例子,介绍自定义命名空间 context component-scan 节点的解析过程。

 

正文


首先,我们回到Spring IoCparseCustomElement详解中的代码块5NamespaceHandlerSupport.parse方法,代码如下。


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

element <context:component-scan /> 节点时,findParserForElement(element, parserContext) 会返回 ComponentScanBeanDefinitionParser,接着执行 ComponentScanBeanDefinitionParser.parse 方法。

 

ComponentScanBeanDefinitionParser.parse


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

4.构建和配置 ClassPathBeanDefinitionScanner见代码块1详解

5.使用 scanner 在指定的 basePackages 包中执行扫描,返回已注册的 BeanDefinitionHolder见代码块5详解

6.组件注册,见代码块16详解

 

代码块1configureScanner


protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
    // 1.解析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.
    // 2.构建ClassPathBeanDefinitionScanner,将bean定义注册委托给scanner类
    ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
    scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults());
    scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
    // 3.解析resource-pattern属性
    if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
        scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
    }
    try {
        // 4.解析name-generator属性
        parseBeanNameGenerator(element, scanner);
    }
    catch (Exception ex) {
        parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
    }
    try {
        // 5.解析scope-resolver、scoped-proxy属性
        parseScope(element, scanner);
    }
    catch (Exception ex) {
        parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
    }
    // 6.解析类型过滤器
    parseTypeFilters(element, scanner, parserContext);
    return scanner;
}

2.构建 ClassPathBeanDefinitionScanner见代码块2详解

6.解析类型过滤器,见代码块4详解

 

代码块2createScanner

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) {
        // 1.注册默认的filter
        registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}

1.注册默认的 filter见代码块3详解

 

代码块3registerDefaultFilters


protected void registerDefaultFilters() {
    // 1.添加@Component注解Filter到includeFilters中
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        // 2.添加@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 {
        // 3.添加@Named注解Filter到includeFilters中,这边会抛ClassNotFoundException
        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.
    }
}

这边会尝试添加3AnnotationTypeFilter includeFilters 中,但是默认情况下,添加 @Named 注解对应的 AnnotationTypeFilter 时会抛异常。因此,执行完该方法,includeFilters 会有两个 AnnotationTypeFilter,分别对应@Component 注解和 @ManagedBean 注解,如下图所示。

image.png


代码块4parseTypeFilters


protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
    // Parse exclude and include filter elements.
    ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
    NodeList nodeList = element.getChildNodes();
    // 1.遍历解析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>
                 */
                // 2.解析include-filter子节点
                if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
                    // 2.1 构建TypeFilter
                    TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
                    // 2.2 添加到scanner的includeFilters属性
                    scanner.addIncludeFilter(typeFilter);
                }
                // 3.解析exclude-filter子节点
                else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
                    // 3.1 构建TypeFilter
                    TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
                    // 3.2 添加到scanner的excludeFilters属性
                    scanner.addExcludeFilter(typeFilter);
                }
            } catch (Exception ex) {
                parserContext.getReaderContext().error(
                        ex.getMessage(), parserContext.extractSource(element), ex.getCause());
            }
        }
    }
}
protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader, ParserContext parserContext) {
    // 1.获取type、expression
    String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
    String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
    expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);
    try {
        // 2.根据filterType,返回对应的TypeFilter,例如annotation返回AnnotationTypeFilter
        if ("annotation".equals(filterType)) {
            // 2.1 指定过滤的注解, expression为注解的类全名称, 例如: org.springframework.stereotype.Controller
            return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
        }
        else if ("assignable".equals(filterType)) {
            // 2.2 指定过滤的类或接口, 包括子类和子接口, expression为类全名称
            return new AssignableTypeFilter(classLoader.loadClass(expression));
        }
        else if ("aspectj".equals(filterType)) {
            // 2.3 指定aspectj表达式来过滤类, expression为aspectj表达式字符串
            return new AspectJTypeFilter(expression, classLoader);
        }
        else if ("regex".equals(filterType)) {
            // 2.4 通过正则表达式来过滤类, expression为正则表达式字符串
            return new RegexPatternTypeFilter(Pattern.compile(expression));
        }
        else if ("custom".equals(filterType)) {
            // 2.5 用户自定义过滤器类型, 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);
    }
}

举个例子:


我们知道,当我们配置了 component-scan 时,Spring会去扫描 base-package 下所有使用了@Component(包括@Controller@Repository@Service注解的bean。这是因为 use-default-filters 属性默认值为 true,而通过代码块3我们知道,use-default-filters = true 时,includeFilters 会有两个AnnotationTypeFilter,分别对应 @Component 注解和@ManagedBean 注解。


如果我们想排除掉使用了 @Controller 注解的 bean 时,就可以使用exclude-filter 属性,例如以下配置。


<context:component-scan base-package="com.joonwhee.open.demo">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

代码块5doScan

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

2.扫描 basePackage,将符合要求的 bean 定义全部找出来,见代码块6详解

4.解析 @Scope 注解,见代码块9详解

6.进一步处理 BeanDefinition 对象,见代码块10详解

7.处理定义在目标类上的通用注解,见代码块11详解

8.检查 beanName 是否已经注册过,如果注册过,检查是否兼容,见代码块12详解

10.根据 proxyMode 的值(步骤4中解析了该属性),选择是否创建作用域代理,见代码块13详解

11.注册 BeanDefinition见代码块15详解

 

代码块6findCandidateComponents

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

5.使用过滤器检查给定的类是否为候选类,见代码块7详解

6.判断 sbd 是否为候选类,步骤5是使用过滤器进行检查,而本方法则是单纯的校验候选者类,见代码块8详解

 

代码块7isCandidateComponent


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;
}

这边的excludeFilters includeFilters 在上面的代码块3、代码块4中已经介绍过。默认情况下excludeFilters 为空,includeFilters 包含:@Component 注解的TypeFilter@ManagedBean 注解的 TypeFilter


因此,在正常情况下,使用了 @Component(包括被 @Component 修饰的@Controller@Repository@Service注解的类在这边会返回 true,表示该类是候选者类。

 

代码块8isCandidateComponent

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()))));
}

正常使用,在前两个条件校验完就会返回 true,不会走到后面两个条件。

 

代码块9resolveScopeMetadata

@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;
}

如果使用了@Scope注解,则解析注解的属性。这边的 defaultProxyMode 取决于代码块1步骤5 scope-resolverscoped-proxy属性,默认为 ScopedProxyMode.NO。可以通过 scoped-proxy 来设置,例如下面配置 defaultProxyMode 的值就为ScopedProxyMode.TARGET_CLASS

<context:component-scan base-package="com.joonwhee.open.demo" scoped-proxy="targetClass">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

 

代码块10postProcessBeanDefinition

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));
    }
}

 

代码块11processCommonDefinitionAnnotations

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"));
        }
    }
}


代码块12checkCandidate

protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
    // 1.如果该注册表(beanDefinitionMap缓存)没有包含beanName, 则返回true,代表可以注册该bean定义
    if (!this.registry.containsBeanDefinition(beanName)) {
        return true;
    }
    // 2.如果注册表中包含beanName
    // 2.1拿到注册表中该beanName的BeanDefinition
    BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
    // 2.2拿到原始BeanDefinition(使用了代理的BeanDefinition会有原始BeanDefinition)
    BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
    if (originatingDef != null) {
        // 2.3如果有原始BeanDefinition, 则使用原始BeanDefinition
        existingDef = originatingDef;
    }
    // 3.检查新BeanDefinition是否与原BeanDefinition兼容,如果兼容则返回false,跳过注册
    if (isCompatible(beanDefinition, existingDef)) {
        return false;
    }
    // 4.如果不兼容,则抛异常
    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() + "]");
}

 

代码块13applyScopedProxyMode

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

3.使用相应的代理模式,创建一个 scope 代理,见代码块14详解

 

代码块14createScopedProxy

public static BeanDefinitionHolder createScopedProxy(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
                                                     BeanDefinitionRegistry registry, boolean proxyTargetClass) {
  // 拿到原始bean的beanName
  String originalBeanName = definition.getBeanName();
  // 拿到原始bean的BeanDefinition
  BeanDefinition targetDefinition = definition.getBeanDefinition();
  // 为原始bean生成了一个新的beanName(加了个前缀: scopedTarget.)
  String targetBeanName = getTargetBeanName(originalBeanName);
  // Create a scoped proxy definition for the original bean name,
  // "hiding" the target bean in an internal target definition.
  // 使用ScopedProxyFactoryBean作为beanClass创建代理BeanDefinition
  RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
  // 将原始bean封装成BeanDefinitionHolder,设置到代理的decoratedDefinition属性
  proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
  // 设置代理的原始BeanDefinition属性值
  proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
  proxyDefinition.setSource(definition.getSource());
  proxyDefinition.setRole(targetDefinition.getRole());
  proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
  if (proxyTargetClass) {
    // 根据类做代理, proxyTargetClass属性默认为true,因此我们不需要在此处设置它
    targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
    // ScopedProxyFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
  } else {
    // 根据接口做代理, 设置proxyTargetClass属性值为false
    proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
  }
  // Copy autowire settings from original bean definition.
  // 从原始bean定义复制autowire设置
  proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
  proxyDefinition.setPrimary(targetDefinition.isPrimary());
  if (targetDefinition instanceof AbstractBeanDefinition) {
    proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
  }
  // The target bean should be ignored in favor of the scoped proxy.
  // 隐藏原始的bean
  targetDefinition.setAutowireCandidate(false);
  targetDefinition.setPrimary(false);
  // Register the target bean as separate bean in the factory.
  // 注册原始bean的BeanDefinition
  registry.registerBeanDefinition(targetBeanName, targetDefinition);
  // Return the scoped proxy definition as primary bean definition
  // (potentially an inner bean).
  // 将代理bean封装成BeanDefinitionHolder对象并返回
  return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

代码块15registerBeanDefinition

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

调用BeanDefinitionReaderUtils 工具类来完成 BeanDefinition 的注册,该方法在Spring IoCparseDefaultElement详解中的代码块13已经解析过。

 

代码块16registerComponents

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

4.在给定的注册表中注册所有用于注解的bean 后置处理器,见代码块17详解

 

代码块17registerAnnotationConfigProcessors

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, Object source) {
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            // 1.设置dependencyComparator属性
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            // 2.设置autowireCandidateResolver属性(设置自动注入候选对象的解析器,用于判断BeanDefinition是否为候选对象)
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
    // 3.注册内部管理的用于处理@Configuration注解的后置处理器的bean
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        // 3.1 registerPostProcessor: 注册BeanDefinition到注册表中
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    // 4.注册内部管理的用于处理@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));
    }
    // 5.注册内部管理的用于处理@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));
    }
    // 6.注册内部管理的用于处理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));
    }
    // 7.注册内部管理的用于处理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));
    }
    // 8.注册内部管理的用于处理@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));
    }
    // 9.注册内部管理用于生产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;
}

3.1 注册后置处理器的 BeanDefinition 到注册表中,见代码块18详解

 

代码块18registerPostProcessor

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

2.注册 BeanDefinition,该方法会走到 DefaultListableBeanFactory.registerBeanDefinition 方法,该方法在Spring IoCparseDefaultElement详解中的代码块14已经解析过。

 

至此,<context:component-scan>节点解析已经完成,主要做的事情有:

1.    扫描 base-package 目录,将使用了@Component@Controller@Repository@Service注解的 bean 注册到注册表中(其实就是beanDefinitionMapbeanDefinitionNamesaliasMap缓存中),跟之前解析默认命名空间一样,也是在后续创建 bean 时需要使用这些缓存。

2.    添加了几个内部的注解相关的后置处理器:ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorRequiredAnnotationBeanPostProcessor等。

 

总结


同时,本文的结束,也标志着 obtainFreshBeanFactory 方法的详解正式结束。

简单来说,有以下几个主要操作:


1.    根据 web.xml contextConfigLocation 配置的路径,读取 Spring 配置文件,并封装成 Resource

2.    根据 Resource 加载XML 配置文件,并解析成 Document 对象

3.    拿到 Document 中的根节点,遍历根节点和所有子节点。

4.    根据命名空间,进行不同的解析,将 bean 节点内容解析成BeanDefinition

5.     BeanDefinition 注册到注册表中(也就是beanDefinitionMapbeanDefinitionNamesaliasMap缓存)。


执行完obtainFreshBeanFactory 方法,我们得到了三个重要的对象:

·       新的 BeanFactory

·       beanDefinitionNames 缓存。

·       beanDefinitionMap 缓存。

这三个对象在之后的 IoC 构建过程中会发挥重要的作用。

 

 

相关文章
|
1月前
|
XML 缓存 Java
Spring源码之 Bean 的循环依赖
循环依赖是 Spring 中经典问题之一,那么到底什么是循环依赖?简单说就是对象之间相互引用, 如下图所示: 代码层面上很好理解,在 bean 创建过程中 class A 和 class B 又经历了怎样的过程呢? 可以看出形成了一个闭环,如果想解决这个问题,那么在属性填充时要保证不二次创建 A对象 的步骤,也就是必须保证从容器中能够直接获取到 B。 一、复现循环依赖问题 Spring 中默认允许循环依赖的存在,但在 Spring Boot 2.6.x 版本开始默认禁用了循环依赖 1. 基于xml复现循环依赖 定义实体 Bean java复制代码public class A {
|
2月前
|
监控 数据可视化 关系型数据库
微服务架构+Java+Spring Cloud +UniApp +MySql智慧工地系统源码
项目管理:项目名称、施工单位名称、项目地址、项目地址、总造价、总面积、施工准可证、开工日期、计划竣工日期、项目状态等。
307 6
|
2月前
|
Java 关系型数据库 数据库连接
Spring源码解析--深入Spring事务原理
本文将带领大家领略Spring事务的风采,Spring事务是我们在日常开发中经常会遇到的,也是各种大小面试中的高频题,希望通过本文,能让大家对Spring事务有个深入的了解,无论开发还是面试,都不会让Spring事务成为拦路虎。
35 1
|
1月前
|
Java 测试技术 数据库连接
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
【Spring源码解读!底层原理高级进阶】【下】探寻Spring内部:BeanFactory和ApplicationContext实现原理揭秘✨
|
1月前
|
Java 数据库连接 API
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】
49 0
|
7天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
22天前
|
XML Java 数据格式
Spring(一)IOC小案例
Spring(一)IOC小案例
|
1月前
|
Java Spring
使用spring实现邮件的发送(含测试,源码,注释)
使用spring实现邮件的发送(含测试,源码,注释)
7 0
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (下)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界
|
1月前
|
XML Java 数据格式
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)
Spring 的奇幻起源:从 IoC 容器到 Bean 的魔法世界 (上)