(一)Spring源码——注册BeanDefinition


typora-copy-images-to: imgs

1. 程序入口

程序入口:

public class MainTest {
	public static void main(String[] args) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
    }
}

2. AnnotationConfigApplicationContext构造

通过点进 AnnotationConfigApplicationContext 进去,源码如下:

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    /*
      创建 BeanDefinitionReader 和 BeanDefinitionScanner 
      
    */
    this();
    // 将我们的配置类注册为 BeanDefinition
    register(annotatedClasses);
    // IoC容器刷新 关键步骤!
    refresh();
}

3. refresh

以上只有三个方法,其中关键 Spring 源码中的关键代码都在 refresh() 方法之中,点进 refresh() 方法,如下:
refresh() 方法中

	@Override
	public void refresh() throws BeansException, IllegalStateException {
		// 同步,线程安全; 防止 fresh还没结束  就又进入改方法 导致容器初始化错乱
		synchronized (this.startupShutdownMonitor) {
          		 // ...
          
				invokeBeanFactoryPostProcessors(beanFactory);

          
				// ...
			}
			// ...
		}
	}

4. 执行 postProcessor

在上述的 invokeBeanFactoryPostProcessors(beanFactory) 方法中将 Bean 扫描为 BeanDefinition,注册进 BeanDefinitionMap 中,点进该方法,如下:

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
		// ...
	}

5. postProcessor具体执行流程

主要核心流程在上述代码中,点进如下:PostProcessorRegistrationDelegate # invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();

    // BeanDefinitionRegistry 是唯一一个定义了 BeanDefinition 注册功能的接口
    if (beanFactory instanceof BeanDefinitionRegistry) { 
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        /*
           1.执行硬编码注册的后处理器(即我们通过代码加入的 BeanPostProcessor,如果没有指定的话,这个for循环不会执行)
        */
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }



        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();


        // 2.获取 BeanDefinitionRegistryPostProcessor.class 类型的 bean 的名字 BeanName
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            /* 2.1先执行优先级是 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor
                  这里执行 ConfigurationClassPostProcessor 处理器,该处理器实现了 PriorityOrdered 接口
            */
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        // 2.2执行 ConfigurationClassPostProcessor
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // 3.和步骤2一样获取 BeanName 一样
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            // 3.1执行优先级是 Ordered 的 postProcessor
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // CGLib代理
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // BeanFactoryPostProcessor.class类型
    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
    // 筛选出bean工程中存在的所有实现BeanFactoryPostProcessor类的类名称

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
            // 已经存在了,不再处理
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 为PriorityOrdered类型
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 为Ordered类型
            orderedPostProcessorNames.add(ppName);
        }
        else {
            // 这个就是我们当前需要关心的PostProcessors
            //nonOrderedPostProcessors添加的不是bean实例,而是BeanDefinition
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}

6. 执行ConfigurationClassPostProcessor

从上边方法的 2.2 处的方法点进去,如下:

private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}

上边方法中核心代码只有一行,即执行处理器,点进如下:ConfigurationClassPostProcessor # postProcessBeanDefinitionRegistry

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    // ...
    processConfigBeanDefinitions(registry);
}

7. 具体执行ConfigurationClassPostProcessor

点进上述方法:ConfigurationClassPostProcessor # processConfigBeanDefinitions

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
  
    // 1.先去获取当前已经注册的所有的 BeanDefinition
    // 这里获取的 BeanDefinition 有两类
    // 一类是Spring自身已经注册的Bean
    // 另一类是我们自己注册的配置文件,即 Appconfig,这个 BeanDefinition 是在容器刷新 refresh() 方法之前通过 register(annotatedClasses) 注册的
    String[] candidateNames = registry.getBeanDefinitionNamess();

    // 2.在这里对已经注册的 BeanDefinition 进行筛选,将我们的配置类 AppConfi 筛选出来加入到 configCandidates 集合中
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
                ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // 如果没有 @Configuration 标注的配置类,那么就不需要进行解析了,直接返回
    if (configCandidates.isEmpty()) {
        return;
    }

    // ... 如果有多个配置类进行排序

    // 去设置自定义的 BeanNameGenerator,如果我们没设置,那么就获取不到
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(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 {
        /*
        ********************3.解析配置类****************************
        */
        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());
        }
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);

        candidates.clear();
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(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());
    }

    if (this.metadataReaderFactory instanceof 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) this.metadataReaderFactory).clearCache();
    }
}

8. 对配置类进行解析

上述步骤3的解析方法,点进去,如下: ConfigurationClassParser # parse

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    // configCandidates 即为传进来的配置类
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            // 表示是注解类型的 BeanDefinition,我们在本次示例使用的就是注解类型的,因此会进入这里第一个 parse 方法
            if (bd instanceof AnnotatedBeanDefinition) {
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }
            else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                parse(((AbstractBeanDefinition) bd).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);
        }
    }

    this.deferredImportSelectorHandler.process();
}

点进上边第一个 parse 方法,如下: ConfigurationClassParser # parse

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

点进上边方法,如下:ConfigurationClassParser # processConfigurationClass

protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
		// ...

		// 将配置类包装成为 SourceClass ,方便统一解析
		SourceClass sourceClass = asSourceClass(configClass);
		do {
             /******************解析配置类*********************/
			sourceClass = doProcessConfigurationClass(configClass, sourceClass);
		}
		while (sourceClass != null);

		this.configurationClasses.put(configClass, configClass);
	}

9. 处理配置类上的注解

点进上边解析配置类的方法,如下: ConfigurationClassParser # doProcessConfigurationClass

@Nullable
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
        throws IOException {

    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        // 如果配置类还有嵌套的内部类,先进行处理
        processMemberClasses(configClass, sourceClass);
    }

    // 1.处理 @PropertySource 注解
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
            sourceClass.getMetadata(), PropertySources.class,
            org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            processPropertySource(propertySource);
        }
        else {
            logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                    "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // 2.处理 @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) {
            /************************2.1 通过扫描器去扫描 @ComponentScan 标注路径下的类******************************/
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                    this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
          
            // ... 进行一些其他的小处理
        }
    }

    // Process any @Import annotations
    processImports(configClass, sourceClass, getImports(sourceClass), true);

    // Process any @ImportResource annotations
    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
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    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;
}

10. 处理配置类的@Component

2.1 上述代码分支: ComponentScanAnnotationParser # parse

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
            componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

    // ... 设置scanner的一些属性,包括 includeFilters 和 excludeFilters

    // 拿到扫描路径
    Set<String> basePackages = new LinkedHashSet<>();
    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);
        }
    });
    /*****************************核心代码,进行扫描*********************************/
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}

11. 扫描basePackage

点进 scanner.doScan,如下:ClassPathBeanDefinitionScanner # 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) {
        // 1.对 basePackage 扫描得到 BeanDefinition 的集合
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        for (BeanDefinition candidate : candidates) {
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                // 2.将 BeanDefinition 设置成默认的 BeanDefinition
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 3.处理 BeanDefinition 的通用注解,包括 @Lazy、@Primary、@DependsOn、@Role、@Description 注解
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            // 4. 判断当前 beanDefinition 是否与其他 BeanDefinition 存在冲突,如果不冲突,返回true
            if (checkCandidate(beanName, candidate)) {
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder =
                        AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 5.注册 BeanDefinition
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

12. 扫描得到BeanDefinition集合

对上述代码 1. 步骤,即扫描 basePackage 的方法,点进去,如下:ClassPathScanningCandidateComponentProvider # findCandidateComponents

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
        return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
    }
    else {
        // 核心代码
        return scanCandidateComponents(basePackage);
    }
}

点进上述方法,如下:ClassPathScanningCandidateComponentProvider # scanCandidateComponents

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<>();
    try {
        // 1.先去拿到 class 文件所在路径,即:classpath*:com/analysis/service/**/*.class
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                resolveBasePackage(basePackage) + '/' + this.resourcePattern;
        // 2.将 class 文件封装为 Resource 对象,这个 Resource 就是用来封装底层资源的,Resource 继承了 InputStreamSource
        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 {
                    /**
                    3.通过MetadataReaderFactory解析Resource对象得到MetadataReader
                      这里返回的 MetaDataReader 其实就是 SimpleMetadataReader,该类就是用于解析 class 文件之后,提供对 class 文件访问的接口
                      getMetadataReaderFactory() 获取的就是 CachingMetadataReaderFactory 对象,将 resource(也就是class文件) 解析成 MetadataReader 之后,将 <resource, MetadataReader> 的 K,V 键值对缓存在 CachingMetadataReaderFactory 对象中
                     (MetadataReaderFactory具体的实现类为:CachingMetadataReaderFactory
                      MetadataReader的具体实现类为:SimpleMetadataReader)
                     */
                    MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                    /**
                    4.通过 include 、 exclude 、 @Conditional 三个条件进行过滤
                     */
                    if (isCandidateComponent(metadataReader)) {
                        // 5.先生成该 Bean 的 ScannedGenericBeanDefinition 对象
                        ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                        sbd.setResource(resource);
                        sbd.setSource(resource);
                        // 6.再判断是不是对应的类是不是接口或抽象类
                        if (isCandidateComponent(sbd)) {
                            if (debugEnabled) {
                                logger.debug("Identified candidate component class: " + resource);
                            }
                            // 7.如果筛选通过,那么就表示扫描到了一个 Bean,将 ScannedGenericBeanDefinition 加入结果集
                            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;
}

13.注册BeanDefinition

在上述代码中,我们拿到了 basePackage 下的所有的符合条件的类,接下来要继续回到 11. 扫描basePackage(ctrl+左键跳转) 中,对扫描到的 BeanDefinition 集合进行处理,处理之后,要对得到的 BeanDefinition 进行注册,即进入到 11. 扫描basePackage 的步骤5的代码中,如下:ClassPathBeanDefinitionScanner # registerBeanDefinition

protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}

点进,如下:BeanDefinitionReaderUtils # registerBeanDefinition

public static void registerBeanDefinition(
        BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
        throws BeanDefinitionStoreException {

    String beanName = definitionHolder.getBeanName();
    // 1.通过beanName ,注册BeanDefinition
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

    // Register aliases for bean name, if any.
    // 如果有别名,则通过别名注册
    String[] aliases = definitionHolder.getAliases();
    if (aliases != null) {
        for (String alias : aliases) {
            registry.registerAlias(beanName, alias);
        }
    }
}

14. 根据beanName注册BeanDefinition

点进上边代码步骤1,如下:DefaultListableBeanFactory # registerBeanDefinition

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "Bean name must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");

    // 校验 BeanDefinition
    if (beanDefinition instanceof AbstractBeanDefinition) {
        try {
            ((AbstractBeanDefinition) beanDefinition).validate();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                    "Validation of bean definition failed", ex);
        }
    }
    // 首先从 beanDefinitionMap 查看是否已经存在 
    BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
    if (existingDefinition != null) {
        // 如果已经存在且不允许覆盖,抛出异常
        if (!isAllowBeanDefinitionOverriding()) {
            throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
        }
        else if (existingDefinition.getRole() < beanDefinition.getRole()) {
            // 0 ROLE_APPLICATION表示这个 Bean 是用户自己定义的 Bean;
            // 1 ROLE_SUPPORT 表示这个 Bean 是某些复杂配置的支撑部分;
            // 2 ROLE_INFRASTRUCTURE 表示这是一个 Spring 内部的 Bean
            // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
            if (logger.isInfoEnabled()) {
                logger.info("Overriding user-defined bean definition for bean '" + beanName +
                        "' with a framework-generated bean definition: replacing [" +
                        existingDefinition + "] with [" + beanDefinition + "]");
            }
        }
        else if (!beanDefinition.equals(existingDefinition)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Overriding bean definition for bean '" + beanName +
                        "' with a different definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Overriding bean definition for bean '" + beanName +
                        "' with an equivalent definition: replacing [" + existingDefinition +
                        "] with [" + beanDefinition + "]");
            }
        }
        // 将解析的 BeanDefinition 放入 Map
        this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    else { // 如果 Map 中不存在已经解析好的 BeanDefinition
        
        // 工厂的 Bean 的创建是否已经开始
        if (hasBeanCreationStarted()) {
            // 加锁,控制并发
            synchronized (this.beanDefinitionMap) {
                //将一个一个的beanDefinition放入到一个Map中(即为IoC容器)
                this.beanDefinitionMap.put(beanName, beanDefinition);
                List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                updatedDefinitions.addAll(this.beanDefinitionNames);
                updatedDefinitions.add(beanName);
                this.beanDefinitionNames = updatedDefinitions;
                removeManualSingletonName(beanName);
            }
        }
        else {
            // Still in startup registration phase
            // 仍在启动注册阶段  添加key-value形式的bean定义信息
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.beanDefinitionNames.add(beanName);
            removeManualSingletonName(beanName);
        }
        this.frozenBeanDefinitionNames = null;
    }

    // 如果已经存在 或者 包含beanName
    if (existingDefinition != null || containsSingleton(beanName)) {
        // 重置所有beanName对应的缓存
        resetBeanDefinition(beanName);
    }
}

15. 完成注册

至此,BeanDefinition的注册就完成了,也就是完成了9. 处理配置类上的注解的步骤2.1的代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/12610.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

智慧园区综合管理平台开发基本功能有哪些?

随着智慧城市建设与信息化发展&#xff0c;园区管理也需要更加智能便捷化&#xff0c;于是智慧园区管理系统开发应运而生。智慧园区综合管理系统就是利用物联网、大数据等技术工具&#xff0c;顺应产业园区升级发展需求&#xff0c;实现园区环境、设备、安全、基础管理、资源服…

TensorFlow Lite,ML Kit 和 Flutter 移动深度学习:1~5

原文&#xff1a;Mobile Deep Learning with TensorFlow Lite, ML Kit and Flutter 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的…

vue关于echarts后端返回格式取值方法

在vue中&#xff0c;接口返回如下数据&#xff1a; data: {充电桩: [0, 0, 78], 红外摄像头: [0, 0, 0], 火焰探测器: [0, 1, 0], 烟雾传感器: [0, 1, 1], 限流保护器: [0, 0, 1]}&#xff0c; 其中数组里第一个值应该放在data1&#xff0c;第二个放在data2&#xff0c;第三个…

docker学习

安装 curl -fsSL https://get.docker.com -o get-docker.sh sudo sh get-docker.sh为了防止后面权限有问题&#xff0c;执行下面这个 sudo groupadd docker sudo gpasswd -a $USER docker newgrp docker基本操作 获得镜像 docker pull hello-world运行 docker run hello-w…

蓝桥杯欲伸手CTF?有多远爬多远

注意&#xff1a;网络安全类比赛 或者说 CTF 参赛不会需要任何费用 只有国赛/省赛有可能会收取一定运维费用 其他比赛都不会收费 望周知。 先来看个特离谱的事情 早上起床看到几位师傅的朋友圈一脸懵&#xff0c;再仔细一看&#xff0c;好嘛。。。。。。 先看看探姬的回复 接下…

如何使用ChatGPT在1天内完成毕业论文

如何使用ChatGPT在1天内完成毕业论文 几天前&#xff0c;亲眼见证了到一位同学花了1天时间用ChatGPT完成了他的毕业论文&#xff0c;世道要变&#xff0c;要学会使用黑科技才能混的下去。废话到此结束&#xff0c;下面说明这么用AI生成自己的论文。 使用工具&#xff1a; 1. P…

VMware vSphere 8.0 Update 1 正式版发布 - 企业级工作负载平台

ESXi 8.0 U1 & vCenter Server 8.0 U1 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vsphere-8-u1/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 2023-04-18&#xff0c;VMware vSphere 8.0 Update 1 正式…

Excel技能之排名,小函数很强大

你还在熬夜加班搞Excel吗&#xff1f; 你还在用手指&#xff0c;指着电脑屏幕&#xff0c;一行一行核对数据吗&#xff1f; 你还在害怕被笑而不敢问同事吗&#xff1f; 赶紧来学Excel&#xff0c;收藏加关注&#xff0c;偷偷地进步&#xff01;日积月累&#xff0c;必成大器&am…

ADIDAS阿里纳斯励志广告语

系列文章目录 精选优美英文短文1——Dear Basketball&#xff08;亲爱的篮球&#xff09;精选优美英文短文2——Here’s to the Crazy Ones&#xff08;致疯狂的人&#xff09;“我祝你不幸并痛苦”——约翰罗伯茨毕业致辞“亲爱的波特兰——CJ麦科勒姆告别信” Hi, I’m Gilb…

Java阶段二Day05

Java阶段二Day05 文章目录 Java阶段二Day05截至此版本可实现的流程图为V14UserControllerClientHandlerDispatcherServletHttpServletResponseHttpServletRequest V15DispatcherServletHttpServletResponseHttpServletRequest V16HttpServletRequestHttpServletResponse 反射JA…

【Linux网络服务】DNS域名解析服务服务

一、BIND域名服务基础 服务背景 1在日常生活中人们习惯使用域名访问服务器&#xff0c;但机器向互相只认IP地址&#xff0c;域名与IP地址之间是多对一的关系&#xff0c;一个IP址不一定只对应一个域名&#xff0c;且一个完成域名只可以对应一个IP地址&#xff0c;它们之间转换…

【数据结构】解析队列各接口功能实现

目录 前言&#xff1a; 一、队列概述&#xff1a; 1.队列的概念&#xff1a; 二、队列的各种接口功能实现&#xff1a; 1.初始化队列&#xff1a; 2.入队&#xff08;尾插&#xff09;&#xff1a; 3.出队&#xff08;头删&#xff09;&#xff1a; 4.查看队头&#xf…

PyTorch 深度学习实战 | 基于 ResNet 的花卉图片分类

“工欲善其事&#xff0c;必先利其器”。如果直接使用 Python 完成模型的构建、导出等工作&#xff0c;势必会耗费相当多的时间&#xff0c;而且大部分工作都是深度学习中共同拥有的部分&#xff0c;即重复工作。所以本案例为了快速实现效果&#xff0c;就直接使用将这些共有部…

YAML /Excel /CSV?自动化测试测试数据管理应用,测试老鸟总结...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 自动化测试无论是…

ChatGPT实战100例 - (02) 自动出PPT它不香么?

文章目录 ChatGPT实战100例 - (02) 自动出PPT它不香么&#xff1f;一、需求与思路1. 需求&#xff1a;出个PPT&#xff0c;5分钟后要用2. 思路&#xff1a;生成markdown然后转化 二、生成markdown语法的思维导图1. 问题2. 回答 三、把markdown文本转换成PPT ChatGPT实战100例 -…

MIMO-OFDM无线通信技术(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本代码为MIMO-OFDM无线通信技术及MATLAB实现。分为十章&#xff0c;供大家学习。 &#x1f4da;2 运行结果 主函数部分代码&a…

Mysql安装详细教程

数据库相关概念 而目前主流的关系型数据库管理系统的市场占有率排名如下&#xff1a; Oracle&#xff1a;大型的收费数据库&#xff0c;Oracle公司产品&#xff0c;价格昂贵。 MySQL&#xff1a;开源免费的中小型数据库&#xff0c;后来Sun公司收购了MySQL&#xff0c;而Oracle…

逆向-还原代码之(*point)[4]和char *point[4] (Interl 64)

// source code #include <stdio.h> #include <string.h> #include <stdlib.h> /* * char (*point)[4] // 数组指针。 a[3][4] // 先申明二维数组,用它来指向这个二维数组 * char *point[4] // 指针数组。 a[4][5] // 一连串的指针…

知识点学习登记备份信息

知识点记录 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ovilnIi-1681441105895)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20211228090433836.png)] [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上…

全景丨0基础学习VR全景制作,平台篇第五章:开场封面功能

大家好欢迎观看蛙色平台使用教程 开场封面功能&#xff0c;现已支持开场图片和开场视频两种呈现方式&#xff0c; 分别针对PC端和移动设备访问分别设置呈现图片、视频内容&#xff0c;满足市场主流需求。 开场图片 传达主旨 1、全局-开场封面-图片 2、分别对PC端和移动设备访…