Spring IOC源码:<context:component-scan>源码详解

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Spring IOC源码:<context:component-scan>源码详解

文章目录

Spring源码系列:

前言

正文

方法1:configureScanner

方法2:createScanner

方法3:registerDefaultFilters

方法4:parseTypeFilters

方法5:createTypeFilter

方法6:doScan

方法7:findCandidateComponents

方法8:isCandidateComponent

方法9:isCandidateComponent

方法10:resolveScopeMetadata

方法11:generateBeanName

方法12:postProcessBeanDefinition

方法13:processCommonDefinitionAnnotations

方法14:checkCandidate

方法15:applyScopedProxyMode

方法16:createScopedProxy

方法17:registerBeanDefinition

方法18:registerComponents

方法19:registerAnnotationConfigProcessors

方法20:registerPostProcessor

总结

Spring源码系列:

Spring IOC源码:简单易懂的Spring IOC 思路介绍

Spring IOC源码:核心流程介绍

Spring IOC源码:ApplicationContext刷新前准备工作

Spring IOC源码:obtainFreshBeanFactory 详解(上)

Spring IOC源码:obtainFreshBeanFactory 详解(中)

Spring IOC源码:obtainFreshBeanFactory 详解(下)

Spring IOC源码:<context:component-scan>源码详解

Spring IOC源码:invokeBeanFactoryPostProcessors 后置处理器详解

Spring IOC源码:registerBeanPostProcessors 详解

Spring IOC源码:实例化前的准备工作

Spring IOC源码:finishBeanFactoryInitialization详解

Spring IoC源码:getBean 详解

Spring IoC源码:createBean( 上)

Spring IoC源码:createBean( 中)

Spring IoC源码:createBean( 下)

Spring IoC源码:finishRefresh 完成刷新详解

前言

前面我们讲解了自定义命名空间过程及其如何去创建自定义命名空间解析器、xsd文件等,实现了一个demo。这节学习一下< context:component-scan>标签对包进行扫描。

正文

回到自定义标签解析方法中:

  public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
    //获取命名空间处理器地址
    String namespaceUri = getNamespaceURI(ele);
    if (namespaceUri == null) {
      return null;
    }
    //加载处理器
    NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
    if (handler == null) {
      error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
      return null;
    }
    //查找解析器进行处理
    return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
  }

进入handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));

  public BeanDefinition parse(Element element, ParserContext parserContext) {
    //根据节点标签查找解析器
    BeanDefinitionParser parser = findParserForElement(element, parserContext);
    return (parser != null ? parser.parse(element, parserContext) : null);
  }

因为我们当前节点标签为,所以查找后的解析器为ComponentScanBeanDefinitionParser。

  public BeanDefinition parse(Element element, ParserContext parserContext) {
    //获取需要扫描的包路径base-package
    String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
    //解析占位符
    basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
    //根据这些“,; \t\n”符号进行切割;如:com.zdc.project1;com.zdc.project2   
    String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
        ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
    // 创建配置扫描器
    ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
    //扫描带特定配置注解的类,如@component
    Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
    //组件注册(包括注册一些内部的注解后置处理器、触发注册事件)
    registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
    return null;
  }

configureScanner(parserContext, element),见方法1详解

scanner.doScan(basePackages),见方法6详解

registerComponents(parserContext.getReaderContext(), beanDefinitions, element),见方法18详解

方法1:configureScanner

  protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
    //默认配置过滤器,如@Component及其带@Component注解的@Service、@Controller
    boolean useDefaultFilters = true;
    if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
      //如果有配置该属性,则解析获取
      useDefaultFilters = Boolean.parseBoolean(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
    }
    // 创建扫描器
    ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters);
    //设置Bean默认解析配置
    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属性,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;
  }

createScanner(parserContext.getReaderContext(),见方法2详解

parseTypeFilters(element, scanner, parserContext),见方法4详解

方法2:createScanner

  protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
    return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters,
        readerContext.getEnvironment(), readerContext.getResourceLoader());
  }
  public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
      Environment environment, @Nullable ResourceLoader resourceLoader) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
    //如果使用默认过滤器
    if (useDefaultFilters) {
      registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
  }


registerDefaultFilters(),见方法3详解

方法3:registerDefaultFilters

  protected void registerDefaultFilters() {
    //添加@Component注解类型
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
      //添加ManagedBean注解类型
      this.includeFilters.add(new AnnotationTypeFilter(
          ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
      logger.trace("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注解类型
      this.includeFilters.add(new AnnotationTypeFilter(
          ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
      logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
      // JSR-330 API not available - simply skip.
    }
  }

方法4:parseTypeFilters

protected void parseTypeFilters(Element element, ClassPathBeanDefinitionScanner scanner, ParserContext parserContext) {
    // Parse exclude and include filter elements.
    ClassLoader classLoader = scanner.getResourceLoader().getClassLoader();
    //获取子节点标签列表
    NodeList nodeList = element.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {
      Node node = nodeList.item(i);
      if (node.getNodeType() == Node.ELEMENT_NODE) {
        //获取节点标签名称
        String localName = parserContext.getDelegate().getLocalName(node);
        try {
          //如果为<context:include-filter>
          if (INCLUDE_FILTER_ELEMENT.equals(localName)) {
            //解析节点属性信息
            TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
            scanner.addIncludeFilter(typeFilter);
          }
          //如果为<context:exclude-filter>
          else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
            //解析节点属性信息
            TypeFilter typeFilter = createTypeFilter((Element) node, classLoader, parserContext);
            scanner.addExcludeFilter(typeFilter);
          }
        }
        catch (ClassNotFoundException ex) {
          parserContext.getReaderContext().warning(
              "Ignoring non-present type filter class: " + ex, parserContext.extractSource(element));
        }
        catch (Exception ex) {
          parserContext.getReaderContext().error(
              ex.getMessage(), parserContext.extractSource(element), ex.getCause());
        }
      }
    }
  }

createTypeFilter((Element) node, classLoader, parserContext),见方法5详解

方法5:createTypeFilter

protected TypeFilter createTypeFilter(Element element, @Nullable ClassLoader classLoader,
      ParserContext parserContext) throws ClassNotFoundException {
    //获取type属性值
    String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
    //获取expression属性值
    String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
    //解析占位符
    expression = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(expression);
    //下面根据不同的类型创建不同的过滤器类
    if ("annotation".equals(filterType)) {
      return new AnnotationTypeFilter((Class<Annotation>) ClassUtils.forName(expression, classLoader));
    }
    else if ("assignable".equals(filterType)) {
      return new AssignableTypeFilter(ClassUtils.forName(expression, classLoader));
    }
    else if ("aspectj".equals(filterType)) {
      return new AspectJTypeFilter(expression, classLoader);
    }
    else if ("regex".equals(filterType)) {
      return new RegexPatternTypeFilter(Pattern.compile(expression));
    }
    else if ("custom".equals(filterType)) {
      Class<?> filterClass = ClassUtils.forName(expression, classLoader);
      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);
    }
  }

xml配置文件示例如下:

  <context:component-scan base-package="service.scan"
              annotation-config="true"
              name-generator="org.springframework.context.annotation.AnnotationBeanNameGenerator"
              resource-pattern="**/*.class"
              scope-resolver="org.springframework.context.annotation.AnnotationScopeMetadataResolver"
              use-default-filters="false">
    <!-- 扫描所有带@Component的类 -->
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
    <!-- assignable是对类或接口进行扫描 -->
    <context:include-filter type="assignable" expression="service.scan.domain.Teacher"/>
    <!-- 注意:在use-default-filters="false"的情况下,exclude-filter是针对include-filter里的内容进行排除 -->
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="assignable" expression="service.scan.domain.College"/>
    <!-- 通配符排除 -->
    <context:exclude-filter type="regex" expression=".service.*"/>
  </context:component-scan>

方法6:doScan

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
    //遍历对包进行扫描
    for (String basePackage : basePackages) {
      //通过解析扫描,经过过滤后的BeanDefinition
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      for (BeanDefinition candidate : candidates) {
        //解析设置Scope元属性信息
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
        candidate.setScope(scopeMetadata.getScopeName());
        //生成bean名称,如果没有名称注解,则使用默认生成,以首字母小写类名为beanName
        String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
        if (candidate instanceof AbstractBeanDefinition) {
          //给当前BeanDefinition设置默认值
          postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
        }
        if (candidate instanceof AnnotatedBeanDefinition) {
          //解析设置一些公共属性值,包括@Lazy, @Primary, @DependsOn, @Role, @Description
          AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
        }
        //检查该类是否注册过,如果注册过看是否兼容
        if (checkCandidate(beanName, candidate)) {
          BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
          definitionHolder =
              AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
          beanDefinitions.add(definitionHolder);
          registerBeanDefinition(definitionHolder, this.registry);
        }
      }
    }
    return beanDefinitions;
  }

findCandidateComponents(basePackage),见方法7

this.scopeMetadataResolver.resolveScopeMetadata(candidate),见方法10详解

this.beanNameGenerator.generateBeanName(candidate, this.registry),见方法11详解

postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName),见方法12详解

AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate),见方法13详解

checkCandidate(beanName, candidate),见方法14详解

AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);,见方法15详解

registerBeanDefinition(definitionHolder, this.registry),将方法17详解

方法7:findCandidateComponents

  public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    //默认componentsIndex 为空,会走下面逻辑
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
      return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    }
    else {
      return scanCandidateComponents(basePackage);
    }
  }

进入 scanCandidateComponents(basePackage)

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
      //拼接查询的包路径,如classpath*:service/scan/**/*.class
      String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
          resolveBasePackage(basePackage) + '/' + this.resourcePattern;
      //解析包下的所有文件资源路径,
      //如file [D:\Code\SourceCode\LeanCode\Spring\spring-framework-5.2.0.RELEASE\learn-test\build\classes\java\main\service\scan\dao\StudentDao.class]
      Resource[] resources = getResourcePatternResolver().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 = getMetadataReaderFactory().getMetadataReader(resource);
            //根据过滤器判断进行校验
            if (isCandidateComponent(metadataReader)) {
              //创建ScannedGenericBeanDefinition类用于封装扫描出来类的属性
              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.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;
  }

isCandidateComponent(metadataReader),见方法8详解

isCandidateComponent(sbd),见方法9详解

方法8:isCandidateComponent

  protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    //根据不同的过滤器类型进行不同逻辑的解析处理,用于排除
    for (TypeFilter tf : this.excludeFilters) {
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
        return false;
      }
    }
    //根据不同的过滤器类型进行不同逻辑的解析处理,用于添加
    for (TypeFilter tf : this.includeFilters) {
      // 如果metadataReader与includeFilters中的任意一个TypeFilter匹配(如果tf为Component注解:metadataReader对应的类使用了Component则匹配),
      if (tf.match(metadataReader, getMetadataReaderFactory())) {
        // 判断是由有@Conditional;如果有,则返回true,表示metadataReader对应的类为候选类
        return isConditionMatch(metadataReader);
      }
    }
    return false;
  }

方法9: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()))));
  }

方法10:resolveScopeMetadata

  public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
    //创建ScopeMetadata,默认属性为singleton 单例
    ScopeMetadata metadata = new ScopeMetadata();
    if (definition instanceof AnnotatedBeanDefinition) {
      AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
      //获取Scope属性
      AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(
          annDef.getMetadata(), this.scopeAnnotationType);
      if (attributes != null) {
        //不为空,设置Scope属性
        metadata.setScopeName(attributes.getString("value"));
        // 解析proxyMode属性
        ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
        if (proxyMode == ScopedProxyMode.DEFAULT) {
          proxyMode = this.defaultProxyMode;
        }
        metadata.setScopedProxyMode(proxyMode);
      }
    }
    return metadata;
  }

这里会创建ScopeMetadata类,默认Scope属性值为Singleton,解析是否有@Scope注解值,有则解析设置。

方法11:generateBeanName

  @Override
  public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    if (definition instanceof AnnotatedBeanDefinition) {
      String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
      if (StringUtils.hasText(beanName)) {
        // Explicit bean name found.
        return beanName;
      }
    }
    // 构建默认名称,以类名并且第一个字母小写
    return buildDefaultBeanName(definition, registry);
  }
  /**
   * Derive a bean name from one of the annotations on the class.
   * @param annotatedDef the annotation-aware bean definition
   * @return the bean name, or {@code null} if none is found
   */
  @Nullable
  protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
    //获取元注解信息
    AnnotationMetadata amd = annotatedDef.getMetadata();
    //获取注解类型
    Set<String> types = amd.getAnnotationTypes();
    String beanName = null;
    for (String type : types) {
      //获取value属性
      AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
      //判断是否ManagedBean、Component、Named注解,及其attributes 是否有value属性
      if (attributes != null && isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
        Object value = attributes.get("value");
        if (value instanceof String) {
          String strVal = (String) value;
          if (StringUtils.hasLength(strVal)) {
            if (beanName != null && !strVal.equals(beanName)) {
              throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
                  "component names: '" + beanName + "' versus '" + strVal + "'");
            }
            beanName = strVal;
          }
        }
      }
    }
    return beanName;
  }

方法12:postProcessBeanDefinition

  protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
    //给当前BeanDefinition设置默认一些配置值,
    beanDefinition.applyDefaults(this.beanDefinitionDefaults);
    if (this.autowireCandidatePatterns != null) {
      //设置AutowireCandidate属性默认为true,代表可以被其它类注入
      beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
    }
  }
  public void applyDefaults(BeanDefinitionDefaults defaults) {
    Boolean lazyInit = defaults.getLazyInit();
    if (lazyInit != null) {
      setLazyInit(lazyInit);
    }
    setAutowireMode(defaults.getAutowireMode());
    setDependencyCheck(defaults.getDependencyCheck());
    setInitMethodName(defaults.getInitMethodName());
    setEnforceInitMethod(false);
    setDestroyMethodName(defaults.getDestroyMethodName());
    setEnforceDestroyMethod(false);
  }

方法13:processCommonDefinitionAnnotations

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
  }
  static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    //获取@Lazy注解,并设置属性值
    AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
    if (lazy != null) {
      abd.setLazyInit(lazy.getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata) {
      //获取不到看其元注解上级有没有
      lazy = attributesFor(abd.getMetadata(), Lazy.class);
      if (lazy != null) {
        abd.setLazyInit(lazy.getBoolean("value"));
      }
    }
    //获取设置@Primary,当属性注入有多个时,配置了Primary将作为首先
    if (metadata.isAnnotated(Primary.class.getName())) {
      abd.setPrimary(true);
    }
    //解析设置@DependsOn,设置该类依赖其它类,被依赖类也会被创建管理
    AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
    if (dependsOn != null) {
      abd.setDependsOn(dependsOn.getStringArray("value"));
    }
    //解析设置@Role
    AnnotationAttributes role = attributesFor(metadata, Role.class);
    if (role != null) {
      abd.setRole(role.getNumber("value").intValue());
    }
    //解析设置@Description
    AnnotationAttributes description = attributesFor(metadata, Description.class);
    if (description != null) {
      abd.setDescription(description.getString("value"));
    }
  }

方法14:checkCandidate

protected boolean checkCandidate(String beanName, BeanDefinition beanDefinition) throws IllegalStateException {
    //判断已经注册缓存中是否存在该beanName
    if (!this.registry.containsBeanDefinition(beanName)) {
      return true;
    }
    //获取已存在的BeanDefinition 
    BeanDefinition existingDef = this.registry.getBeanDefinition(beanName);
    //获取原始BeanDefinition ,代理的会有原始值
    BeanDefinition originatingDef = existingDef.getOriginatingBeanDefinition();
    if (originatingDef != null) {
      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() + "]");
  }


方法15:applyScopedProxyMode

  static BeanDefinitionHolder applyScopedProxyMode(
      ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {
    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    //如果不代理,则返回原始值
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
      return definition;
    }
    //判断代理方式,基于类还是基于接口;基于类:使用Cglib,基于接口:JDK动态代理
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
  }

ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass),见方法16详解

方法16:createScopedProxy

  public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
      BeanDefinitionRegistry registry, boolean proxyTargetClass) {
    //获取原始beanName
    String originalBeanName = definition.getBeanName();
    //获取原始BeanDefinition 
    BeanDefinition targetDefinition = definition.getBeanDefinition();
    //为原始beanName重新生成一个名称,原始BeanName名称加上前缀 scopedTarget.
    String targetBeanName = getTargetBeanName(originalBeanName);
    //使用ScopedProxyFactoryBean作为要创建代理的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());
    //添加类属性,值为新生成的beanName
    proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
    if (proxyTargetClass) {
      //使用Cglib代理方式,设置属性值,ScopedProxyFactoryBean的该属性默认就为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 {
      //使用JDK动态代理方式,设置属性值
      proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
    }
    // Copy autowire settings from original bean definition.
    //拷贝原始对象的信息
    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注册到缓存中
    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());
  }

方法17:registerBeanDefinition

  protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
  }
  public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {
    // Register bean definition under primary name.
    String beanName = definitionHolder.getBeanName();
    //往beanDefinitionNames放BeanName,往beanDefinitionMap放 <beanName:BeanDefinitionHolder >
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
    // Register aliases for bean name, if any.
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
      //往aliasMap放 <alias:beanName>
      for (String alias : aliases) {
        registry.registerAlias(beanName, alias);
      }
    }
  }

注册过程,我们在解析默认命名空间配置的时候也有讲解到,主要往三个缓存添加beanDefinitionMap、beanDefinitionNames、aliasMap。

方法18:registerComponents

  protected void registerComponents(
      XmlReaderContext readerContext, Set<BeanDefinitionHolder> beanDefinitions, Element element) {
    Object source = readerContext.extractSource(element);
    //获取标签节点名称,并封装成CompositeComponentDefinition 对象
    CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), source);
    //将扫描到的所有BeanDefinition添加到compositeDef的nestedComponents属性中
    for (BeanDefinitionHolder beanDefHolder : beanDefinitions) {
      compositeDef.addNestedComponent(new BeanComponentDefinition(beanDefHolder));
    }
    // Register annotation config processors, if necessary.
    boolean annotationConfig = true;
    //获取annotation-config属性值
    if (element.hasAttribute(ANNOTATION_CONFIG_ATTRIBUTE)) {
      annotationConfig = Boolean.parseBoolean(element.getAttribute(ANNOTATION_CONFIG_ATTRIBUTE));
    }
    if (annotationConfig) {
      //注册并返回一些默认配置的后置处理器
      Set<BeanDefinitionHolder> processorDefinitions =
          AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source);
      for (BeanDefinitionHolder processorDefinition : processorDefinitions) {
        compositeDef.addNestedComponent(new BeanComponentDefinition(processorDefinition));
      }
    }
    readerContext.fireComponentRegistered(compositeDef);
  }

AnnotationConfigUtils.registerAnnotationConfigProcessors(readerContext.getRegistry(), source),见方法19详解

方法19:registerAnnotationConfigProcessors

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      BeanDefinitionRegistry registry, @Nullable Object source) {
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
      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;
  }

registerPostProcessor方法,见方法20详解

方法20:registerPostProcessor

  private static BeanDefinitionHolder registerPostProcessor(
      BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
    //设置默认Role属性
    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    //往beanDefinitionMap、beanDefinitionNames缓存放入
    registry.registerBeanDefinition(beanName, definition);
    //新建包装类
    return new BeanDefinitionHolder(definition, beanName);
  }


到这里 < context:component-scan> 节点解析已经完成了

总结

整个解析过程已经做了一遍了,现在梳理一下流程:

1、获取包路径、对路径进行占位符替换,根据“,;\n\t”解析成路径数组

2、创建扫描器,解析配置过滤器,如果是默认过滤器则include加入默认注解属性,如:Compenent、ManagedBean、Named;以及自定义过滤器属性处理,如:

<context:include-filter type=“assignable” expression=“service.scan.domain.Teacher”/>

<context:exclude-filter type=“assignable” expression=“service.scan.domain.College”/>

3、开始扫描,遍历包路径,拼接通配符,加载包下面的资源,如xxx.class

4、 扫描出类,加载元注解属性,并经过过滤器处理。

5、得到BeanDinifition后,设置公共属性,判断是否需要代理,以及解析代理方法是使用Cglib,还是JDK动态代理

6、注册到上下文缓存中,beanDefinitionMap、beanDefinitionNames、aliasMap。

7、添加了几个内部的注解相关的后置处理器:ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor 等。


本章就讲解到这里,整个解析工作告一段落了。后面开始讲解IOC 流程中的后置处理器处理,及其多播器等,最后再进入最核心部分,Bean实例化初始化工作。






目录
相关文章
|
1月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
6天前
|
缓存 Java 开发工具
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
三级缓存是Spring框架里,一个经典的技术点,它很好地解决了循环依赖的问题,也是很多面试中会被问到的问题,本文从源码入手,详细剖析Spring三级缓存的来龙去脉。
Spring是如何解决循环依赖的?从底层源码入手,详细解读Spring框架的三级缓存
|
6天前
|
XML 缓存 Java
手写Spring源码(简化版)
Spring包下的类、手写@ComponentScan注解、@Component注解、@Autowired注解、@Scope注解、手写BeanDefinition、BeanNameAware、InitializingBean、BeanPostProcessor 、手写AnnotationConfigApplicationContext
手写Spring源码(简化版)
|
6天前
|
缓存 安全 Java
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
从底层源码入手,通过代码示例,追踪AnnotationConfigApplicationContext加载配置类、启动Spring容器的整个流程,并对IOC、BeanDefinition、PostProcesser等相关概念进行解释
Spring框架中Bean是如何加载的?从底层源码入手,详细解读Bean的创建流程
|
6天前
|
XML Java 数据格式
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
Spring 第二节内容补充 关于Bean配置的更多内容和细节 万字详解!
55 18
Spring IOC—基于XML配置Bean的更多内容和细节(通俗易懂)
|
23天前
|
人工智能 前端开发 Java
【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)
本文介绍了如何使用 **Spring Cloud Alibaba AI** 构建基于 Spring Boot 和 uni-app 的聊天机器人应用。主要内容包括:Spring Cloud Alibaba AI 的概念与功能,使用前的准备工作(如 JDK 17+、Spring Boot 3.0+ 及通义 API-KEY),详细实操步骤(涵盖前后端开发工具、组件选择、功能分析及关键代码示例)。最终展示了如何成功实现具备基本聊天功能的 AI 应用,帮助读者快速搭建智能聊天系统并探索更多高级功能。
168 2
【实操】Spring Cloud Alibaba AI,阿里AI这不得玩一下(含前后端源码)
|
7天前
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
7天前
|
Java 数据库连接 Maven
Spring基础1——Spring(配置开发版),IOC和DI
spring介绍、入门案例、控制反转IOC、IOC容器、Bean、依赖注入DI
Spring基础1——Spring(配置开发版),IOC和DI
|
1月前
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式
|
29天前
|
设计模式 Java 程序员
学习 Spring 源码的意义是什么呢?
研究Spring源码能深化框架理解,提升代码分析与设计能力,助您掌握设计模式及最佳实践,增强解决问题的效率,促进职业生涯发展,并激发技术热情。选择稳定版本,从核心模块开始,结合实际项目并参与社区,让学习之旅既充实又具乐趣。