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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 在 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 构建过程中会发挥重要的作用。

 

 

相关文章
|
11天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
39 2
|
28天前
|
数据采集 监控 前端开发
二级公立医院绩效考核系统源码,B/S架构,前后端分别基于Spring Boot和Avue框架
医院绩效管理系统通过与HIS系统的无缝对接,实现数据网络化采集、评价结果透明化管理及奖金分配自动化生成。系统涵盖科室和个人绩效考核、医疗质量考核、数据采集、绩效工资核算、收支核算、工作量统计、单项奖惩等功能,提升绩效评估的全面性、准确性和公正性。技术栈采用B/S架构,前后端分别基于Spring Boot和Avue框架。
|
17天前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
41 9
|
26天前
|
XML 缓存 Java
搞透 IOC、Spring IOC ,看这篇就够了!
本文详细解析了Spring框架的核心内容——IOC(控制反转)及其依赖注入(DI)的实现原理,帮助读者理解如何通过IOC实现组件解耦,提高程序的灵活性和可维护性。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
|
1月前
|
前端开发 Java 数据库
SpringBoot学习
【10月更文挑战第7天】Spring学习
36 9
|
1月前
|
XML Java 数据格式
Spring学习
【10月更文挑战第6天】Spring学习
21 1
|
18天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
31 0
|
1月前
|
Java 测试技术 开发者
springboot学习四:Spring Boot profile多环境配置、devtools热部署
这篇文章主要介绍了如何在Spring Boot中进行多环境配置以及如何整合DevTools实现热部署,以提高开发效率。
68 2
|
1月前
|
前端开发 Java 程序员
springboot 学习十五:Spring Boot 优雅的集成Swagger2、Knife4j
这篇文章是关于如何在Spring Boot项目中集成Swagger2和Knife4j来生成和美化API接口文档的详细教程。
111 1
|
1月前
|
Java API Spring
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
这篇文章是关于Spring Boot 2.x中拦截器的入门教程和实战项目场景实现的详细指南。
28 0
springboot学习七:Spring Boot2.x 拦截器基础入门&实战项目场景实现
下一篇
无影云桌面