对于postProcessor的管理
创始人
2025-05-30 00:17:17
0

postProcessor介绍

beanPostProcessor,这是在每个bean陷入初始化时会调用的。

BeanDefinitionRegistryPostProcessor,这是beanFactoryProcessor的子类,它的存在意义在于真正执行beanFactoryProcessor之前注册进入更多的bean,包括beanFactoryProcessor这种bean。这点我们可以从它的专用待实现方法postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)中看出,它传入了注册中心,这样我们就可以把新的beanDefinition直接注册进去了。
对于BeanDefinitionRegistryPostProcessor而言,如果是一开始就加入List 的话,那会最优先执行,在此之后,会分别以PriorityOrdered,Ordered,其余顺序执行。由于ConfigurationClassPostProcessor属于PriorityOrdered,所以如果通过@Component注入的BeanDefinitionRegistryPostProcessor设置为PriorityOrdered是无效的。

beanFactoryProcessor,这是工厂执行的后置处理器,在开始bean的创建前,会调用完所有beanFactoryProcessor和BeanDefinitionRegistryPostProcessor的后置处理方法postProcessBeanFactory()。在refresh方法中,先完成beanFactoryProcessor和BeanDefinitionRegistryPostProcessor的调用,然后完成beanPostProcessor的bean初始化,然后最后才会到达其它bean的初始化。

// 空实现
postProcessBeanFactory(beanFactory);// 完成beanFactoryProcessor和BeanDefinitionRegistryPostProcessor的调用
invokeBeanFactoryPostProcessors(beanFactory);// 在beanDefinition中找到所有BeanPostProcessor,完成getBean()并且往beanPostProcessors加入
registerBeanPostProcessors(beanFactory);.........................................................// bean的真正创建
finishBeanFactoryInitialization(beanFactory);

invokeBeanFactoryPostProcessors()

关于BeanDefinitionRegistryPostProcessor的执行

public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) {// 这个集合用来承装所有执行过并且会生成beanDefinition的BeanDefinitionRegistry,这是在后续调用所有BeanFactoryPostProcessorSet processedBeans = new HashSet<>();// AnnotationConfigApplicationContext就是BeanDefinitionRegistry的实现,所以一定进入if (beanFactory instanceof BeanDefinitionRegistry) {BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;List regularPostProcessors = new ArrayList<>();List registryProcessors = new ArrayList<>();// 如果是BeanDefinitionRegistryPostProcessor,那么调用并加入集合,否则就是BeanFactoryPostProcessor,先不调用,加入集合,等到后续集中调用for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {BeanDefinitionRegistryPostProcessor registryProcessor =(BeanDefinitionRegistryPostProcessor) postProcessor;registryProcessor.postProcessBeanDefinitionRegistry(registry);registryProcessors.add(registryProcessor);}else {regularPostProcessors.add(postProcessor);}}// 这个列表是用来承装这一次BeanDefinitionRegistryPostProcessorList currentRegistryProcessors = new ArrayList<>();// 将所有最高优先级处理器拿出来,挨个执行,并放入processedBeansString[] postProcessorNames =beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));processedBeans.add(ppName);}}sortPostProcessors(currentRegistryProcessors, beanFactory);registryProcessors.addAll(currentRegistryProcessors);invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);currentRegistryProcessors.clear();// 将所有优先级处理器拿出来,挨个执行,并放入processedBeanspostProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);for (String ppName : postProcessorNames) {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();// 一直执行所有BeanDefinitionRegistryPostProcessor,直到所有都进入了processedBeansboolean 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();}// 可以看成将所有processedBeans加上beanFactoryPostProcessors的所有后置处理器共同执行了该方法invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);}else {// Invoke factory processors registered with the context instance.invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);}...
}

关于BeanFactoryPostProcessor的执行

以下逻辑就明确了,将所有BeanFactoryPostProcessor取出来,除了processedBean中那些后置处理器,其余的全部执行一遍

// 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);// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List priorityOrderedPostProcessors = new ArrayList<>();
List orderedPostProcessorNames = new ArrayList<>();
List 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)) {priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {orderedPostProcessorNames.add(ppName);}else {nonOrderedPostProcessorNames.add(ppName);}
}// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);// Finally, invoke all other BeanFactoryPostProcessors.
List nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
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();

关于内部最重要处理器ConfigurationClassPostProcessor

我们可以简要把源码分为三部分
1 识别所有config
2 解析所有config
3 将解析结果全部加入BeanDefinition,重复2 3 步骤

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {List configCandidates = new ArrayList<>();String[] candidateNames = registry.getBeanDefinitionNames();// 把所有拥有@Configuration的beanDefinition加入for (String beanName : candidateNames) {BeanDefinition beanDef = registry.getBeanDefinition(beanName);if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {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));}}// 如果没有if (configCandidates.isEmpty()) {return;}// 给筛选过的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 contextSingletonBeanRegistry 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();}// Parse each @Configuration classConfigurationClassParser parser = new ConfigurationClassParser(this.metadataReaderFactory, this.problemReporter, this.environment,this.resourceLoader, this.componentScanBeanNameGenerator, registry);Set candidates = new LinkedHashSet<>(configCandidates);Set alreadyParsed = new HashSet<>(configCandidates.size());do {// 正式处理按照@Configuration逻辑处理parser.parse(candidates);parser.validate();Set configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());configClasses.removeAll(alreadyParsed);if (this.reader == null) {this.reader = new ConfigurationClassBeanDefinitionReader(registry, this.sourceExtractor, this.resourceLoader, this.environment,this.importBeanNameGenerator, parser.getImportRegistry());}// 对于剩下的@bean,@importResource和importBeanDefinitionRegistrar进行统一生成beanDefinition并注册注入// 并且@import直接指向的普通类一直没有注册成beanDefinition,这里也会完成this.reader.loadBeanDefinitions(configClasses);// alreadyParsed添加所有执行过的configalreadyParsed.addAll(configClasses);candidates.clear();// 对所有beanDefinition进行处理,将没parse过的config再次加入候选者,进行处理,其实也就是70行的那三种beanDefinitionif (registry.getBeanDefinitionCount() > candidateNames.length) {String[] newCandidateNames = registry.getBeanDefinitionNames();Set oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));Set 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 classesif (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();}
}

postProcessBeanFactory无非是一个增强器,作用就是为了非轻量的Configuration在@bean方法反复调用时返回的是同一个对象。

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {// 没用的int factoryId = System.identityHashCode(beanFactory);if (this.factoriesPostProcessed.contains(factoryId)) {throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + beanFactory);}// 都添加了,压根不调用this.factoriesPostProcessed.add(factoryId);if (!this.registriesPostProcessed.contains(factoryId)) {// BeanDefinitionRegistryPostProcessor hook apparently not supported...// Simply call processConfigurationClasses lazily at this point then.processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);}// 做了一下增强,然后加了个后置处理器enhanceConfigurationClasses(beanFactory);beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {Map configBeanDefs = new LinkedHashMap<>();for (String beanName : beanFactory.getBeanDefinitionNames()) {BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);..........................//可以看出,如果不是FULL,那么configBeanDefs就不会有值,不会有值,就会在isEmpty()return,减少了CGLIB增强if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {if (!(beanDef instanceof AbstractBeanDefinition)) {throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +beanName + "' since it is not stored in an AbstractBeanDefinition subclass");}else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {logger.info("Cannot enhance @Configuration bean definition '" + beanName +"' since its singleton instance has been created too early. The typical cause " +"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +"return type: Consider declaring such methods as 'static'.");}configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);}}if (configBeanDefs.isEmpty()) {// nothing to enhance -> return immediatelyreturn;}ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();for (Map.Entry entry : configBeanDefs.entrySet()) {AbstractBeanDefinition beanDef = entry.getValue();// If a @Configuration class gets proxied, always proxy the target classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// Set enhanced subclass of the user-specified bean classClass configClass = beanDef.getBeanClass();Class enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);if (configClass != enhancedClass) {if (logger.isTraceEnabled()) {logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));}beanDef.setBeanClass(enhancedClass);}}
}

识别所有config类

就是满足条件ConfigurationClassUtils.checkConfigurationClassCandidate(…)
也就是满足拥有@Configuration,@Component,@ComponentScan,@Import,@ImportResource其中之一
对于Configuration而言,分为轻量级和非轻量,是通过@Configuration下的属性proxyBeanMethods来判断的,如果是true,那么是非轻量,每次调用getBean()返回单例对象,如果是false,那么是轻量,每次调用new方法返回新的对象。
调用getBean主要是在它的postProcessBeanFactory的增强方法enhanceConfigurationClasses()执行

public @interface Configuration {@AliasFor(annotation = Component.class)String value() default "";boolean proxyBeanMethods() default true;}

以下代码主要干两件事,取出元数据,判断是否是Configuration,无论是轻量还是非轻量

public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {// 取出元数据String className = beanDef.getBeanClassName();if (className == null || beanDef.getFactoryMethodName() != null) {return false;}AnnotationMetadata metadata;if (beanDef instanceof AnnotatedBeanDefinition &&className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {// Can reuse the pre-parsed metadata from the given BeanDefinition...metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();}else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {// Check already loaded Class if present...// since we possibly can't even load the class file for this Class.Class beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||BeanPostProcessor.class.isAssignableFrom(beanClass) ||AopInfrastructureBean.class.isAssignableFrom(beanClass) ||EventListenerFactory.class.isAssignableFrom(beanClass)) {return false;}metadata = AnnotationMetadata.introspect(beanClass);}else {try {MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);metadata = metadataReader.getAnnotationMetadata();}catch (IOException ex) {if (logger.isDebugEnabled()) {logger.debug("Could not find class file for introspecting configuration annotations: " +className, ex);}return false;}}// 分为轻量和非轻量Configuration,只有这两种可以进入Map config = metadata.getAnnotationAttributes(Configuration.class.getName());// 如果是ProxyBeans为true,说明是非轻量if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);}// 如果不是@Configuration,那么看看是不是@Component,@ComponentScan,@Import,@ImportResource其中之一else if (config != null || isConfigurationCandidate(metadata)) {beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);}else {return false;}// 用于下一步Configuration排序使用Integer order = getOrder(metadata);if (order != null) {beanDef.setAttribute(ORDER_ATTRIBUTE, order);}return true;
}

Parser解析Config

protected void processConfigurationClass(ConfigurationClass configClass, Predicate filter) throws IOException {if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {return;}ConfigurationClass existingClass = this.configurationClasses.get(configClass);if (existingClass != null) {// 说明要不就是@Component内部类,要不就是@Import指向的类,都不需要再次执行了if (configClass.isImported()) {// 如果当前有更多import数据,更新进去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);}}// 这一行是生成一个类的加载工具,只需要调用sourceClass.loadClass()就可以获得Config的classSourceClass sourceClass = asSourceClass(configClass, filter);do {sourceClass =  doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass != null);this.configurationClasses.put(configClass, configClass);
}
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate filter)throws IOException {if (configClass.getMetadata().isAnnotated(Component.class.getName())) {// 解析存在内部类注释@Component的情况processMemberClasses(configClass, sourceClass, filter);}// 直接将@propertySource注解对应的.properties文件内容注册到environment的MutablePropertiesfor (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");}}// 处理@ComponentScan注解Set componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);if (!componentScans.isEmpty() &&!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {for (AnnotationAttributes componentScan : componentScans) {// 往内层翻,会发现其实也是对对应路径进行所有类是否有@Component的判断// 这和第一篇文章,spring工厂流程中,scanner的处理有异曲同工之妙,都是利用了ClassPathScanningCandidateComponentProviderSet scannedBeanDefinitions =this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());// 如果发现这个beanDefinition又再次符合config的情况,让它重新执行parser.parse// 这里并不需要beanDefinition的注册了,因为在上面的componentScanParser.parse已经完成了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());}}}}// getImports的用处是将这个类的注解进行递归识别,将所有@import注解都给提取出来// 在这个方法中,会对@Import,@ImportSelector,ImportBeanDefinitionRegistrar进行解析和注册processImports(configClass, sourceClass, getImports(sourceClass), filter, true);// Process any @ImportResource annotationsAnnotationAttributes importResource =AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);if (importResource != null) {String[] resources = importResource.getStringArray("locations");Class readerClass = importResource.getClass("reader");for (String resource : resources) {String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);configClass.addImportedResource(resolvedResource, readerClass);}}// 把所有bean方法取出,加到configclassSet beanMethods = retrieveBeanMethodMetadata(sourceClass);for (MethodMetadata methodMetadata : beanMethods) {configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));}// 把自己所有接口的bean方法也取出,加到configclassprocessInterfaces(configClass, sourceClass);// 如果存在父类,那么就返回父类,这样父类就会执行doProcessConfigurationClassif (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 recursereturn sourceClass.getSuperClass();}}// 完全结束return null;
}
private void collectImports(SourceClass sourceClass, Set imports, Set 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"));}
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,Collection importCandidates, Predicate 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) {// 如果import指向的是selectorif (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine importsClass candidateClass = candidate.loadClass();ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,this.environment, this.resourceLoader, this.registry);Predicate selectorFilter = selector.getExclusionFilter();if (selectorFilter != null) {exclusionFilter = exclusionFilter.or(selectorFilter);}if (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);}else {// 直接取出importselector的返回字符串,然后拿去递归调用                                                                                                                                      String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());Collection importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);}}// 如果import指向的是ImportBeanDefinitionRegistrar,会加到configclass当中去,等待后续处理else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {// Candidate class is an ImportBeanDefinitionRegistrar ->// delegate to it to register additional bean definitionsClass candidateClass = candidate.loadClass();ImportBeanDefinitionRegistrar registrar =ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,this.environment, this.resourceLoader, this.registry);configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());}// 如果import指向的是普通类,当作config类递归使用parser处理else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->// process it as an @Configuration classthis.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);}finally {this.importStack.pop();}}
}

相关内容

热门资讯

English Learnin... English Learning - L2 第 7 次小组纠音 辅音 [p] [b] [t] [d]...
Opencv+Python学习... 一,色彩空间分类1.GRAY色彩空间GRAY(灰度图像)通...
【SSM】MyBatis(三.... 文章目录1.environment2.transactionManager3. dataSource...
甘南七日全景精华游攻略:预算拆... 甘南,这片被《孤独星球》评为“亚洲最佳旅行地”的秘境,集藏地信仰、高原风光、草原牧歌于一体。2025...
Cursor太强了,从零开始写... Cursor太强了,从零开始写ChatGLM大模型的微调代码初次体验对话实录问...
LeetCode题解 19(7... 文章目录子集(78)代码解答目标和(494)代码解答 子集(78) 这道题要求我们返回指定数组的所...
在家也能做!广东叉烧包的美味秘... 在广东点心那琳琅满目的世界里,叉烧包宛如一颗熠熠生辉的甜蜜明珠,以其松软绵密的包子皮和香甜多汁的叉烧...
嬴氏酒以「文化传承」为核心,酱... 嬴氏酒以差异化高品质酱香白酒突围,融合中华文化精髓与古法工艺,精准定位、适配商业模型、把握市场痛点,...
江西小炒烟火气秘诀!爆炒 3 ... 在江西的街头巷尾,总能看到这样的场景:简易的灶台支在店门口,猛火灶呼呼作响,厨师手持铁锅上下翻飞,油...
原创 从... 5月29日,台湾旺旺集团总经理蔡旺庭的发言,直接把人整破防了!他坦诚,旺旺从中国台湾起步,在大陆这片...
从“吸引年轻人”到“成为年轻人... 据后浪研究所发布的《2024年年轻人喝酒报告》显示,00后最爱的网红酒里,汾酒作为唯一上榜的白酒品牌...
亚朵酒店养生早餐获好评,以中式... 近年来,随着健康理念的普及与生活节奏的加快,早餐这一日常场景被重新置于大众视野。而在差旅频繁的客群中...
【XKA六周年特别企划】品牌背... 在大健康的赛道上,愿与XKA合作,开发更多更好的主粮产品,守护家人健康。 2019年通过展会结识XK...
原创 人... 从餐厅搬到火车车厢,自助餐的“边界”正在不断延伸。 据多家媒体报道,近日,从沈阳、大连、长春等地...
黄酒文化发源地:一坛酒,千年香 提起中国酒文化,很多人会立刻想到浓香四溢的白酒,或风情万种的葡萄酒,但却容易忽略了黄酒,这种承载着中...
pikachu——xss 反射性(get)都提示get了,肯定跟url栏有关拿到题目...
传统为体,现代为用:劲牌以古法... 长江吐故纳新,不断拥抱新生,才能涤荡初心,砥砺前行,最终拥抱大海。 “长江第一湾”所在的宜宾美酒也一...
红浪翻滚舌尖舞:口味虾的火辣江... 在湘菜的璀璨版图中,口味虾犹如一簇跃动的红色火焰,以其浓烈奔放的香辣滋味,点燃了无数食客的味蕾。这道...
酒厂老板快看!禁酒令下,中小酒... 嘿,各位酒友、酿酒的小伙伴们,我是酒皇叔王杰老师。最近这禁酒令一出,可把不少中小型酒厂、酒坊的老板们...
嫩滑姜撞奶,一场味蕾的甜蜜之旅... 在广东那五彩斑斓的甜品宇宙里,姜撞奶以一场别开生面的甜蜜邂逅,撩拨着食客们的味蕾,带来令人沉醉的惊喜...