Spring创建Bean源码 - 解析配置类(一)

发现所有的配置类

主要作用发现BeanDefinitionRegistry对象中的配置类**(带有****@Configuration****注解的类),**利用配置类中的特定注解信息派生出更多的BeanDefinition

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    //获取已经注册进来的Bean名称
    String[] candidateNames = registry.getBeanDefinitionNames();

    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        //判断某个类中是否存在 configurationClass属性
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        //判断BeanDefinition是否是一个配置类
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            //配置类加入配置集合
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // Return immediately if no @Configuration classes were found
    if (configCandidates.isEmpty()) {
        return;
    }

    //按照@Order指定的顺序排序BeanDefinition
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // Detect any custom bean name generation strategy supplied through the enclosing application context
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    //创建解析配置类解析对象
    ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
        //开始解析配置类
        //该API包含向Spring中注册springboot的AutoConfiguration自动装配类,并将自动装配类放入org.springframework.context.annotation.ConfigurationClassParser.importStack数据结构中
        parser.parse(candidates);
        parser.validate();
        //去重
        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        //加载所有的配置类,并注册到注册器中
        //读取的配置类ConfigurationClass,将该配置类以及该配置类中@Bean方法中创建的对象封装成BeanDefinition,然后注册到BeanDefinitionRegister中
        //加载带有@ConfigurationProperties注解的类,并封装成BeanDefinition注册到BeanDefinitionRegister中
        this.reader.loadBeanDefinitions(configClasses);

        alreadyParsed.addAll(configClasses);
        processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

        candidates.clear();
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = Set.of(candidateNames);
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());

    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }

    // Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
    this.propertySourceDescriptors = parser.getPropertySourceDescriptors();

    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
        // Clear cache in externally provided MetadataReaderFactory; this is a no-op
        // for a shared cache since it'll be cleared by the ApplicationContext.
        cachingMetadataReaderFactory.clearCache();
    }
}

详细步骤如下:

  1. BeanDefinitionRegistry中获取所有的BeanDefinition
  2. 挑选出所有的配置类
  3. 按照配置类的Order配置的顺序,对所有的配置类进行排序
  4. 创建配置类解析器ConfigurationClassParser,解析每一个配置类并生成ConfigurationClass对象,将每个配置类解析到的数据封装到对应的ConfigurationClass对象中。
  5. 使用ConfigurationClassBeanDefinitionReader对象,将每一个ConfigurationClass中需要派生出来的类加载进来,封装成BeanDefinition,注册到BeanDefinitionRegistry中。

解析所有的配置类

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            //是否是基于注解的BeanDefinition,实现了AnnotatedBeanDefinition接口的BeanDefinition。
            if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef) {
                parse(annotatedBeanDef.getMetadata(), holder.getBeanName());
            } else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef.hasBeanClass()) {
                parse(abstractBeanDef.getBeanClass(), holder.getBeanName());
            } else {
                parse(bd.getBeanClassName(), holder.getBeanName());
            }
        } catch (BeanDefinitionStoreException ex) {
            throw ex;
        } catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
        }
    }

    //Springboot AutoConfiguration自动装配的入口方法
    // @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector.AutoConfigurationGroup#process
    // @see org.springframework.boot.autoconfigure.AutoConfigurationImportSelector#getAutoConfigurationEntry
    this.deferredImportSelectorHandler.process();
}

详细步骤如下:

  1. 根据BeanDefinition的实际类型,调用不同的解析方法
  2. 调用deferredImportSelectorHandler.process()方法,导入其他的BeanDefinition该方法也是**Springboot AutoConfiguration**自动装配的入口方法。请看Springboot自动装配源码(一) - 自动装配

解析配置类

开始解析给定的配置类信息,为每个配置类生成一个ConfigurationClass,然后将所有解析到的配置类信息都填充到ConfigurationClass对象中。

protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
    processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
}

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }

    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    if (existingClass != null) {
        if (configClass.isImported()) {
            if (existingClass.isImported()) {
                existingClass.mergeImportedBy(configClass);
            }
            // Otherwise ignore new imported config class; existing non-imported class overrides it.
            return;
        } else {
            // Explicit bean definition found, probably replacing an import.
            // Let's remove the old one and go with the new one.
            this.configurationClasses.remove(configClass);
            this.knownSuperclasses.values().removeIf(configClass::equals);
        }
    }


    //包含注解元数据的Class的简单包装器,
    SourceClass sourceClass = asSourceClass(configClass, filter);
    do {
        //开始处理配置类
        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    }
    // Recursively process the configuration class and its superclass hierarchy.
    while (sourceClass != null);
    //将扫描到的所有类放入内存
    this.configurationClasses.put(configClass, configClass);
}

/**
 * 通过从SourceClass读取注解、Member和方法来构建一个完整的{@link ConfigurationClass}。
 * <p>
 * 1.处理配置类上的@Component注解
 * 2.处理配置类上的@PropertySource注解
 * 3.处理配置类上的@ComponentScan注解
 * 4.处理配置类上的Import注解
 * 5.处理配置类上的ImportResource注解
 * 6.处理配置类中标记@Bean注解的方法
 * <p>
 * 以上所有步骤得处理结果都会封装到ConfigurationClass对象中,供后续创建Bean的时候使用
 *
 * @param configClass 被构建的配置类
 * @param sourceClass 自动配置类的注解元数据的简单包装类
 * @return 父类或者null
 */
@Nullable
protected final SourceClass doProcessConfigurationClass(
        ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
        throws IOException {
    //配置类是否被@Component注解标记
    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        // Recursively process any member (nested) classes first
        //递归处理任何Member类
        processMemberClasses(configClass, sourceClass, filter);
    }

    // Process any @PropertySource annotations
    //处理任何@PropertySource注解
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {
        if (this.propertySourceRegistry != null) {
            //处理
            this.propertySourceRegistry.processPropertySource(propertySource);
        } else {
            logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // Process any @ComponentScan annotations
    //处理@ComponentScan注解
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
            !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            //带有@ComponentScan注解的类就是配置类,立即执行扫描
            //扫描@ComponentScan注解中basePackages值对应的包,获取包里的所有class,并封装成BeanDefinition加载注册注册器中
            Set<BeanDefinitionHolder> scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // Check the set of scanned definitions for any further config classes and parse recursively if needed
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

    //处理所有 @Import注解
    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    //处理所有 @ImportResource 注解
    AnnotationAttributes importResource =
            AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        String[] resources = importResource.getStringArray("locations");
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // Process individual @Bean methods
    //处理带有@Bean注解的方法
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        //加入配置类
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // 处理接口上的默认方法
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any
    //处理父类
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
                !this.knownSuperclasses.containsKey(superclass)) {
            this.knownSuperclasses.put(superclass, configClass);
            // Superclass found, return its annotation metadata and recurse
            return sourceClass.getSuperClass();
        }
    }

    // No superclass -> processing is complete
    return null;
}

详细步骤如下:

  1. 处理配置类上的@Component注解:如果自动配置类上标有@Component注解,则递归处理嵌套在配置类中嵌套的类。
  2. 处理配置类上的@PropertySource注解:解析@PropertySource注解中的元数据,将@PropertySource注解配置的属性资源加载到Environment中。请看《Spring创建Bean源码 - 解析配置类 (三): 处理PropertySource注解》
  3. 处理配置类上的@ComponentScan注解,请看
  4. 处理配置类上的Import注解
  5. 处理配置类上的ImportResource注解
  6. 处理配置类中标记@Bean注解的方法
  7. 处理接口上的默认方法

处理配置类的@Component注解

略。。。。。


处理配置类的@PropertySource注解

解析@PropertySource注解信息,将注解中配置的属性资源加载到Environment中。

/**
 * 处理@PropertySource注解的元数据
 * @param propertySource metadata for the <code>@PropertySource</code> annotation found
 * @throws IOException if loading a property source failed
 */
void processPropertySource(AnnotationAttributes propertySource) throws IOException {
    //获取name属性值
    String name = propertySource.getString("name");
    if (!StringUtils.hasLength(name)) {
        name = null;
    }
    //获取encoding属性值
    String encoding = propertySource.getString("encoding");
    if (!StringUtils.hasLength(encoding)) {
        encoding = null;
    }
    //获取value属性值
    String[] locations = propertySource.getStringArray("value");
    Assert.isTrue(locations.length > 0, "At least one @PropertySource(value) location is required");
    //获取ignoreResourceNotFound属性值
    boolean ignoreResourceNotFound = propertySource.getBoolean("ignoreResourceNotFound");

    //获取factory属性值
    Class<? extends PropertySourceFactory> factoryClass = propertySource.getClass("factory");
    Class<? extends PropertySourceFactory> factorClassToUse =
            (factoryClass != PropertySourceFactory.class ? factoryClass : null);
    //将@PropertySource注解的元数据封装成PropertySourceDescriptor
    PropertySourceDescriptor descriptor = new PropertySourceDescriptor(Arrays.asList(locations), ignoreResourceNotFound, name,
            factorClassToUse, encoding);
    //将@PropertySource注解配置的属性资源加载到Environment中。
    this.propertySourceProcessor.processPropertySource(descriptor);
    this.descriptors.add(descriptor);
}

/**
 * 通过PropertySourceDescriptor实例的所在的环境处理指定的{@link PropertySourceDescriptor}对象
 * @param descriptor 待处理的PropertySourceDescriptor
 * @throws IOException if loading the properties failed
 */
public void processPropertySource(PropertySourceDescriptor descriptor) throws IOException {
    String name = descriptor.name();
    String encoding = descriptor.encoding();
    List<String> locations = descriptor.locations();
    Assert.isTrue(locations.size() > 0, "At least one @PropertySource(value) location is required");
    boolean ignoreResourceNotFound = descriptor.ignoreResourceNotFound();
    PropertySourceFactory factory = (descriptor.propertySourceFactory() != null ?
            instantiateClass(descriptor.propertySourceFactory()) : DEFAULT_PROPERTY_SOURCE_FACTORY);

    for (String location : locations) {
        try {
            //value属性配置的资源文件的位置
            String resolvedLocation = this.environment.resolveRequiredPlaceholders(location);
            //加载属性资源
            Resource resource = this.resourceLoader.getResource(resolvedLocation);
            //将属性资源加入到environment中
            addPropertySource(factory.createPropertySource(name, new EncodedResource(resource, encoding)));
        }
        catch (IllegalArgumentException | FileNotFoundException | UnknownHostException | SocketException ex) {
            // Placeholders not resolvable or resource not found when trying to open it
            if (ignoreResourceNotFound) {
                if (logger.isInfoEnabled()) {
                    logger.info("Properties location [" + location + "] not resolvable: " + ex.getMessage());
                }
            }
            else {
                throw ex;
            }
        }
    }
}

详细步骤如下:

  1. 解析name、encoding、value、factory属性。
  2. 使用value属性配置的资源文件位置加载属性资源,然后将属性加入到Environment中。

处理配置类的@Import注解

解析配置类上的@Import,并将注解中指定的类注册进来。

/**
 * 获取基于@Import注解配导入的类集合
 */
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
    Set<SourceClass> imports = new LinkedHashSet<>();
    Set<SourceClass> visited = new LinkedHashSet<>();
    collectImports(sourceClass, imports, visited);
    return imports;
}

//递归收集基于@Import注解配导入的类集合
private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
        throws IOException {

    if (visited.add(sourceClass)) {
        for (SourceClass annotation : sourceClass.getAnnotations()) {
            String annName = annotation.getMetadata().getClassName();
            if (!annName.equals(Import.class.getName())) {
                collectImports(annotation, imports, visited);
            }
        }
        imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
    }
}

/**
 * 处理@Import注解中的导入类
 *
 * @param configClass             带有@Configuration注解的配置类
 * @param currentSourceClass      带有@Configuration注解配置类对应的带有注解元数据的简单包装类
 * @param importCandidates        @Configuration注解的配置类上@Import注解中的导入类集合
 * @param exclusionFilter
 * @param checkForCircularImports
 */
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
                            Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
                            boolean checkForCircularImports) {

    if (importCandidates.isEmpty()) {
        return;
    }

    if (checkForCircularImports && isChainedImportOnStack(configClass)) {
        this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
    } else {
        this.importStack.push(configClass);
        try {
            for (SourceClass candidate : importCandidates) {
                //当前导入类实现了ImportSelector接口
                if (candidate.isAssignable(ImportSelector.class)) {
                    Class<?> candidateClass = candidate.loadClass();
                    //反射实例化当前导入类
                    ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                            this.environment, this.resourceLoader, this.registry);
                    Predicate<String> selectorFilter = selector.getExclusionFilter();
                    if (selectorFilter != null) {
                        exclusionFilter = exclusionFilter.or(selectorFilter);
                    }
                    //当前导入类的对象是否是一个DeferredImportSelector
                    //Springboot的自动装配机制就是基于DeferredImportSelector实现的
                    if (selector instanceof DeferredImportSelector deferredImportSelector) {
                        this.deferredImportSelectorHandler.handle(configClass, deferredImportSelector);
                    } 
                    else {
                        //调用ImportSelector的selectImports方法,将方法返回的类集合注册进来
                        String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                        Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                        processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                    }
                }
                //当前导入类实现了ImportBeanDefinitionRegistrar接口
                else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                    //Class实现了ImportBeanDefinitionRegistrar这个接口,称Class是一个ImportBeanDefinitionRegistrar
                    //委托ImportBeanDefinitionRegistrar来注册BeanDefinition
                    //ImportBeanDefinitionRegistrar功能是将@Import注解中的类的BeanDefinition注册到Spring中

                    //configClass上@Import注解中的某一个导入类
                    Class<?> candidateClass = candidate.loadClass();
                    ImportBeanDefinitionRegistrar registrar =
                            ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                    this.environment, this.resourceLoader, this.registry);
                    //4.configClass:带有Import注解的Class
                    //5.保存ImportBeanDefinitionRegistrar对象与@Import元数据的对应关系到configClass对象中
                    configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                }
                //当前导入类是一个普通的类
                else {
                    //@Import注解中的导入类既不是ImportSelector也不是ImportBeanDefinitionRegistrar,就是既没有实现ImportSelector也没有实现ImportBeanDefinitionRegistrar
                    //就当成普通的配置类处理
                    this.importStack.registerImport(
                            currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                    processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                }
            }
        } catch (BeanDefinitionStoreException ex) {
            throw ex;
        } catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                            configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);
        } finally {
            this.importStack.pop();
        }
    }
}

详细步骤如下:

  1. 获取配置类上@Import注解中配置的导入类的集合
  2. 遍历导入类
  3. 如果导入类实现了ImportSelector接口则
    1. 利用反射实例化导入类,如果实例化的对象是一个DeferredImportSelector,则调用DeferredImportSelectorHandler#handle方法,处理以组的方式导入类。(Springboot的自动装配机制就是基于DeferredImportSelector实现的)
    2. 如果实例化的对象是不一个DeferredImportSelector,则调用ImportSelector#selectImports方法,将方法返回的类注册进来。
  4. 如果导入类实现了ImportBeanDefinitionRegistrar接口,则利用反射实例化导入类,委托ImportBeanDefinitionRegistrar来注册BeanDefinition,然后保存ImportBeanDefinitionRegistrar对象与@Import元数据的对应关系到ConfigClass对象中。
  5. 如果当前导入类既不是ImportSelector也不是ImportBeanDefinitionRegistrar,就是既没有实现ImportSelector也没有实现ImportBeanDefinitionRegistrar就当成普通的配置类处理。

处理配置类的@ComponentScans注解

解析配置类上的@ComponentScan注解,并根据其配置的信息,加载指定包下的类并封装成BeanDefinition注册到BeanDefinitionRegistry

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, String declaringClass) {
    //创建ClassPathBeanDefinitionScanner对象,用于扫描和加载Class
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
            componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);
	//获取@Component的nameGenerator属性,用于为BeanDefinition生成Bean名称的类。
    Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
            BeanUtils.instantiateClass(generatorClass));
	//获取@Component的scopedProxy属性,用于确定是否为扫描到的类生成代理,默认false。
    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
        scanner.setScopedProxyMode(scopedProxyMode);
    }
    else {
        Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
        scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    }
	//获取@Component的resourcePattern属性,用于控制符合组件检测条件的类文件。
    scanner.setResourcePattern(componentScan.getString("resourcePattern"));

    //获取@Component的includeFilters、excludeFilters属性,用于控制符合组件检测条件的类文件。
    for (AnnotationAttributes includeFilterAttributes : componentScan.getAnnotationArray("includeFilters")) {
        List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(includeFilterAttributes, this.environment,
                this.resourceLoader, this.registry);
        for (TypeFilter typeFilter : typeFilters) {
            scanner.addIncludeFilter(typeFilter);
        }
    }
    for (AnnotationAttributes excludeFilterAttributes : componentScan.getAnnotationArray("excludeFilters")) {
        List<TypeFilter> typeFilters = TypeFilterUtils.createTypeFiltersFor(excludeFilterAttributes, this.environment,
            this.resourceLoader, this.registry);
        for (TypeFilter typeFilter : typeFilters) {
            scanner.addExcludeFilter(typeFilter);
        }
    }
	//是否是懒加载的
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }
    //扫描的包集合
    Set<String> basePackages = new LinkedHashSet<>();
    //获取@Component注解的basePackages值
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    for (String pkg : basePackagesArray) {
        String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        Collections.addAll(basePackages, tokenized);
    }
    for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
        basePackages.add(ClassUtils.getPackageName(clazz));
    }
    if (basePackages.isEmpty()) {
        basePackages.add(ClassUtils.getPackageName(declaringClass));
    }

    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
        @Override
        protected boolean matchClassName(String className) {
            return declaringClass.equals(className);
        }
    });
    //扫描并加载指定packages中的类
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}

详细代码逻辑为:

  1. 创建ClassPathBeanDefinitionScanner对象,用于扫描和加载Class
  2. 获取@ComponentnameGenerator属性,用于为BeanDefinition生成Bean名称的类。
  3. 获取@ComponentscopedProxy属性,用于确定是否为扫描到的类生成代理,默认false
  4. 获取@ComponentresourcePattern属性,用于控制符合组件检测条件的类文件。
  5. 获取@ComponentincludeFilters、excludeFilters属性,用于控制符合组件检测条件的类文件。
  6. 获取@ComponentlazyInit,用于控制扫描到的类是否是懒加载。
  7. 获取@ComponentbasePackages,用于获取组件扫描的包结构。
  8. 开始扫描和加载

扫描指定包下的类,并将其封装成BeanDefinition注册到BeanDefinitionRegistry中。

/**
 * 1.扫描给定包下的所有Class,封装成BeanDefinitionHolder集合返回
 * 2.将所有的BeanDefinition注册到注册器中
 * @param basePackages ComponentScan注解中的value值
 * @return 并将所有的Class封装成BeanDefinitionHolder集合
 */
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) {
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            //设置Scope属性
            candidate.setScope(scopeMetadata.getScopeName());

            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);

            if (candidate instanceof AbstractBeanDefinition abstractBeanDefinition) {
                postProcessBeanDefinition(abstractBeanDefinition, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition annotatedBeanDefinition) {
                //解析Bean上的特定注解,并丰富BeanDefinition
                AnnotationConfigUtils.processCommonDefinitionAnnotations(annotatedBeanDefinition);
            }
            if (checkCandidate(beanName, candidate)) {
                //BeanDefinition封装成BeanDefinitionHolder
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder =
                        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                //将BeanDefinition注册到注册器中
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}
  1. 扫描包,并将扫描的类封装成BeanDefinition对象
  2. 设置BeanDefinition对应BeanScope属性
  3. 将默认设置应用于BeanDefinition对应Bean
    1. 默认懒加载属性
    2. 默认初始化方法
    3. 默认销毁方法
    4. 默认依赖检查
  4. 解析类中的指定注解,并设置到BeanDefinition中。
    1. @Lazy
    2. @Primary
    3. @DependsOn
    4. @Role
    5. @Description
/**
	 * 解析Bean上某些注解的属性值,并修改Bean的定义信息
	 * @param abd BeanDefinition
	 * @param metadata 注解元数据
	 */
	static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
		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"));
			}
		}

		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
		if (dependsOn != null) {
			abd.setDependsOn(dependsOn.getStringArray("value"));
		}

		AnnotationAttributes role = attributesFor(metadata, Role.class);
		if (role != null) {
			abd.setRole(role.getNumber("value").intValue());
		}
		AnnotationAttributes description = attributesFor(metadata, Description.class);
		if (description != null) {
			abd.setDescription(description.getString("value"));
		}
	}
  1. 根据Scope属性创建BeanDefinitionHolder,替换普通的BeanDefinitionHolder
static BeanDefinitionHolder applyScopedProxyMode(
        ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}
public static BeanDefinitionHolder createScopedProxy(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {

    return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
/**
 * Generate a scoped proxy for the supplied target bean, registering the target
 * bean with an internal name and setting 'targetBeanName' on the scoped proxy.
 * @param definition the original bean definition
 * @param registry the bean definition registry
 * @param proxyTargetClass whether to create a target class proxy
 * @return the scoped proxy definition
 * @see #getTargetBeanName(String)
 * @see #getOriginalBeanName(String)
 */
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
        BeanDefinitionRegistry registry, boolean proxyTargetClass) {

    String originalBeanName = definition.getBeanName();
    BeanDefinition targetDefinition = definition.getBeanDefinition();
    String targetBeanName = getTargetBeanName(originalBeanName);

    // Create a scoped proxy definition for the original bean name,
    // "hiding" the target bean in an internal target definition.
    RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
    proxyDefinition.setDecoratedDefinition(new BeanDefinitionHolder(targetDefinition, targetBeanName));
    proxyDefinition.setOriginatingBeanDefinition(targetDefinition);
    proxyDefinition.setSource(definition.getSource());
    proxyDefinition.setRole(targetDefinition.getRole());

    proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName);
    if (proxyTargetClass) {
        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 {
        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 abd) {
        proxyDefinition.copyQualifiersFrom(abd);
    }

    // The target bean should be ignored in favor of the scoped proxy.
    targetDefinition.setAutowireCandidate(false);
    targetDefinition.setPrimary(false);

    // Register the target bean as separate bean in the factory.
    registry.registerBeanDefinition(targetBeanName, targetDefinition);

    // Return the scoped proxy definition as primary bean definition
    // (potentially an inner bean).
    return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}

处理配置类的@ImportResource注解

//处理所有 @ImportResource 注解
AnnotationAttributes importResource =
        AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
if (importResource != null) {
    String[] resources = importResource.getStringArray("locations");
    Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
    for (String resource : resources) {
        String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
        configClass.addImportedResource(resolvedResource, readerClass);
    }
}

详细代码逻辑:

  1. 获取配置类上的@ImportResourcelocations(资源的位置)和BeanDefinitionReader(用于读取资源的BeanDefinitionReader对象)属性信息。
  2. 遍历locations,解析资源对应的占位符,并将占位符与BeanDefinitionReader的对应关系存入ConfigurationClass对象中的Map<String, Class<? extends BeanDefinitionReader>> importedResources中。

处理配置类中带有@Bean注解的方法

找出配置类中所有的@Bean方法,然后将方法填充到ConfigurationClass中。

//处理带有@Bean注解的方法
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
for (MethodMetadata methodMetadata : beanMethods) {
    //加入配置类
    configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
}
/**
 * 检索所有带有@Bean注解方法的元数据信息
 */
private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) {
    AnnotationMetadata original = sourceClass.getMetadata();
    Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName());
    if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) {
        // Try reading the class file via ASM for deterministic declaration order...
        // Unfortunately, the JVM's standard reflection returns methods in arbitrary
        // order, even between different runs of the same application on the same JVM.
        try {
            AnnotationMetadata asm =
                    this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata();
            Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName());
            if (asmMethods.size() >= beanMethods.size()) {
                Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size());
                for (MethodMetadata asmMethod : asmMethods) {
                    for (MethodMetadata beanMethod : beanMethods) {
                        if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) {
                            selectedMethods.add(beanMethod);
                            break;
                        }
                    }
                }
                if (selectedMethods.size() == beanMethods.size()) {
                    // All reflection-detected methods found in ASM method set -> proceed
                    beanMethods = selectedMethods;
                }
            }
        } catch (IOException ex) {
            logger.debug("Failed to read class file via ASM for determining @Bean method order", ex);
            // No worries, let's continue with the reflection metadata we started with...
        }
    }
    return beanMethods;
}

详细代码逻辑为:

  1. 获取配置类中带有@Bean的所有方法集合,(返回集合中的方法的顺序是任意的,不是按照声明的顺序排列的,因为JVM中反射获取方法的顺序是任意的,即使同一个JVM,同一个应用程序,不同运行之间也顺序也是不同的)。
  2. 尝试通过 ASM 读取类文件的方式使@Bean方法在集合中按照声明顺序排列。