ConfigurationClassPostProcessor处理所有配置类,包括@Component、@Bean、@Import注解等。由于配置类可能会引入新的配置类,新的配置类也需要被处理,所以ConfigurationClassPostProcessor采用do-while循环处理配置类,直到不存在未处理的配置类。
配置类的具体的处理工作交给ConfigurationClassParser,配置类引入新的配置类主要分两种情况:
1、配置类的Member Class是配置类、@ComponentScan扫描到配置类等情况,这些导入到rigistry的新配置类会递归的继续处理,并放到ConfigurationClassParser的configurationClasses属性中,这些都是已经处理过的
2、@Bean、@ImportResource、ImportBeanDefinitionRegistrar等不会直接注册到registry,而是由ConfigurationClassBeanDefinitionReader load到registry,这些配置类没有被处理过
这里的核心逻辑比较简单,如上所述,主要在ConfigurationClassPostProcessor#processConfigBeanDefinitions方法
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); String[] candidateNames = registry.getBeanDefinitionNames(); // 过滤出beanFactory中的配置类 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)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; } // 排序 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); // candidates 待解析的配置类,alreadyParsed已经解析过的配置类 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse"); // 处理每个配置类,@Component、@Import、@ComponentScan、@Bean注解等都在这里处理 parser.parse(candidates); parser.validate(); // parser.getConfigurationClasses()获取到的配置类都被处理过 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()); } // loadBeanDefinitions,@Bean、@ImportResource、ImportBeanDefinitionRegistrar注册bean // 会在这里load到registry,这部分配置类未被处理,后面详细介绍 this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end(); candidates.clear(); // 说明导入了新的bean,可能存在未parse的配置类 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()); } // 将未parse的配置类放入candidates,下一轮do-while循环处理 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(); } }
下面重点介绍do-while循环中两个重要步骤:parse和loadBeanDefinitions
在外层的do-while循环中,将一组配置类解析的具体工作交给ConfigurationClassParser。该类的处理存在递归调用,比较复杂,调用链路简图如下
parse(Set)处理一组配置类,该方法在ConfigurationClassPostProcessor在do-while循环中调用。该方法在for循环中逐个解析所有配置类,最后调用一下deferredImportSelectorHandler,用来处理DeferredImportSelector。
public void parse(Set<BeanDefinitionHolder> configCandidates) { for (BeanDefinitionHolder holder : configCandidates) { BeanDefinition bd = holder.getBeanDefinition(); try { 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方法都调用了processConfigurationClass方法,parse如下,仅仅是将不同的入参统一成ConfigurationClass
protected final void parse(@Nullable String className, String beanName) throws IOException { Assert.notNull(className, "No bean class name for configuration class bean definition"); MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className); processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER); } protected final void parse(Class<?> clazz, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER); } protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException { processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER); }
processConfigurationClass方法处理了三件事情
1、如果当前configClass存在existingClass(配置类已经处理过),如果existingClass和configClass都是被其他配置类导入的,则合并被导入的类,不处理configClass;如果configClass不是被导入的,则重新处理这个类
2、do-while循环遍历一个配置类的所有父类,调用doProcessConfigurationClass处理配置类及每个父类
3、处理完配置类后加入Map configurationClasses
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); } } // Recursively process the configuration class and its superclass hierarchy. SourceClass sourceClass = asSourceClass(configClass, filter); do { sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter); } while (sourceClass != null); this.configurationClasses.put(configClass, configClass); }
doProcessConfigurationClass具体处理每个配置类或其父类,配置类即configClass,当前要处理的类即sourceClass。doProcessConfigurationClass主要获取到sourceClass类、接口、方法、属性上的注解,并进行特定处理,下面分别介绍
标注了@Component都会被处理,MemberClass就是内部类
if (configClass.getMetadata().isAnnotated(Component.class.getName())) { processMemberClasses(configClass, sourceClass, filter); }
processMemberClasses获取sourceClass的所有是配置类的MemberClass,调用processConfigurationClass当作配置类处理,candidate.asConfigClass(configClass)指定了内部类是被哪个配置类导入的。这里会存在递归调用
private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException { Collection<SourceClass> memberClasses = sourceClass.getMemberClasses(); if (!memberClasses.isEmpty()) { List<SourceClass> candidates = new ArrayList<>(memberClasses.size()); for (SourceClass memberClass : memberClasses) { if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) && !memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) { candidates.add(memberClass); } } OrderComparator.sort(candidates); for (SourceClass candidate : candidates) { if (this.importStack.contains(configClass)) { this.problemReporter.error(new CircularImportProblem(configClass, this.importStack)); } else { this.importStack.push(configClass); try { processConfigurationClass(candidate.asConfigClass(configClass), filter); } finally { this.importStack.pop(); } } } } }
PropertySource作用是导入配置文件
通过componentScanParser扫描bean,对扫到的配置类调用parse(String, String)重载方法进行解析,这里也存在递归调用
// Process any @ComponentScan annotations 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) { // The config class is annotated with @ComponentScan -> perform the scan immediately 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注解比较复杂,首先从sourceClass查找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; }
递归方法collectImports。获取sourceClass上所有注解,如果注解不是@Import,继续搜索collectImports查找注解上的@Import;如果注解是@Import,获取Import进来的类,加入到imports
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")); } }
for循环对所有Import进来的类,分四种情况处理
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) { if (candidate.isAssignable(ImportSelector.class)) { // Candidate class is an ImportSelector -> delegate to it to determine imports 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); } if (selector instanceof DeferredImportSelector) { this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); } else { String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter); processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false); } } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // Candidate class is an ImportBeanDefinitionRegistrar -> // delegate to it to register additional bean definitions Class<?> candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry); configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> // process it as an @Configuration class 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); } finally { this.importStack.pop(); } } }
resource里面可能定义了BeanDefinition,通过该注解导入resource。处理该注解仅将resource暂存在configClass里,后续再通过ConfigurationClassBeanDefinitionReader来注册BeanDefinition
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); } }
处理@Bean首先解析出beanMethod,然后暂存在configClass里,后续通过ConfigurationClassBeanDefinitionReader注册BeanDifinition
// Process individual @Bean methods Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); }
递归处理所有接口及父接口的@Bean注解
private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException { for (SourceClass ifc : sourceClass.getInterfaces()) { Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc); for (MethodMetadata methodMetadata : beanMethods) { if (!methodMetadata.isAbstract()) { // A default method or other concrete method on a Java 8+ interface... configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); } } processInterfaces(configClass, ifc); } }
deferredImportSelectorHandler用来处理DeferredImportSelector,有两个重要方法:
1、processImports的时候,如果遇到DeferredImportSelector,调用deferredImportSelectorHandler#handle进行处理
2、parse配置类时候,处理完所有配置类,调用deferredImportSelectorHandler#process方法统一处理DeferredImportSelector
DefferedImportSelector与ImportSelector的区别
processorImports时遇到ImportSelector,会立即selectImport;而对于DefferedImportSelector,会先暂存起来,处理完其他的配置类再统一处理DefferedImportSelector。当使用@Conditional注解注册beanDefinition会很有用。
handler和process方法目的是实现deffered语义,即延迟处理,延迟到当前parse过程的其他配置类都处理过之后,再处理DefferedImportSelector。
handle方法
processImports的过程中会调用handle方法,如果 deferredImportSelectors == null,意味着process, 正在进行(开始process之前会将deferredImportSelectors置为null,这个方法被调用即处理DeferredImportSelector的过程中又import了DeferredImportSelector),此时则直接处理,DeferredImportSelector;否则直接加入list deferredImportSelectors中,等待process处理
process方法
开始process之前,将deferredImportSelectors置为null。然后实例化DeferredImportSelectorGroupingHandler,对所有的DefferedImportSelector注册到handler里,然后调用DeferredImportSelectorGroupingHandler#processGroupImports。
private class DeferredImportSelectorHandler { // 暂存的deferredImportSelector @Nullable private List<DeferredImportSelectorHolder> deferredImportSelectors = new ArrayList<>(); public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) { DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector); if (this.deferredImportSelectors == null) { DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler(); handler.register(holder); handler.processGroupImports(); } else { this.deferredImportSelectors.add(holder); } } public void process() { List<DeferredImportSelectorHolder> deferredImports = this.deferredImportSelectors; this.deferredImportSelectors = null; try { if (deferredImports != null) { DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler(); deferredImports.sort(DEFERRED_IMPORT_COMPARATOR); deferredImports.forEach(handler::register); handler.processGroupImports(); } } finally { this.deferredImportSelectors = new ArrayList<>(); } } }
process过程中,将处理逻辑委托给DeferredImportSelectorGroupingHandler,先register、然后processGroupImports,目的是实现Group语义:即多个DefferedImportSelector为一组,这多个DefferedImportSelector import进来的类可以放在一起,通过特定逻辑决定哪些最终要import进来
先看下DeferredImportSelector接口定义
public interface DeferredImportSelector extends ImportSelector { // 相同Class<? extends Group>为相同的组,为null是DefaultDeferredImportSelectorGroup @Nullable default Class<? extends Group> getImportGroup() { return null; } interface Group { // 一个group中包含多个DeferredImportSelector,会调用该方法逐个处理。处理时需要暂存 // 每个DeferredImportSelector import进来的类 void process(AnnotationMetadata metadata, DeferredImportSelector selector); // 调用process处理所有DeferredImportSelector之后,会调用该方法获取最终要import的类, // 这里面可以实现特定过滤逻辑或其他逻辑 Iterable<Entry> selectImports(); // 封装import的一个className。metadata是配置类的metadata,importClassName是将要import // 的className class Entry { private final AnnotationMetadata metadata; private final String importClassName; public Entry(AnnotationMetadata metadata, String importClassName) { this.metadata = metadata; this.importClassName = importClassName; } } }
Group语义是在DeferredImportSelectorGrouping类实现的,如下
DeferredImportSelectorGrouping封装了Group实例以及多个DeferredImportSelector。getImports调用group#process逐个处理所有的DeferredImportSelector,然后调用group#selectImports获取import的所有类
private static class DeferredImportSelectorGrouping { private final DeferredImportSelector.Group group; private final List<DeferredImportSelectorHolder> deferredImports = new ArrayList<>(); DeferredImportSelectorGrouping(Group group) { this.group = group; } public void add(DeferredImportSelectorHolder deferredImport) { this.deferredImports.add(deferredImport); } public Iterable<Group.Entry> getImports() { for (DeferredImportSelectorHolder deferredImport : this.deferredImports) { this.group.process(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getImportSelector()); } return this.group.selectImports(); } }
默认的Group是DefaultDeferredImportSelectorGroup
process方法就是简单调用selector#selectImports方法,并暂存起来;selectImports方法即返回所有selector import进来的类
private static class DefaultDeferredImportSelectorGroup implements Group { private final List<Entry> imports = new ArrayList<>(); @Override public void process(AnnotationMetadata metadata, DeferredImportSelector selector) { for (String importClassName : selector.selectImports(metadata)) { this.imports.add(new Entry(metadata, importClassName)); } } @Override public Iterable<Entry> selectImports() { return this.imports; } }
另一个实现是AutoConfigurationGroup
process方法也是暂存了所有import的类;selectImports包含了特定的过滤逻辑
private static class AutoConfigurationGroup implements DeferredImportSelector.Group, BeanClassLoaderAware, BeanFactoryAware, ResourceLoaderAware { private final Map<String, AnnotationMetadata> entries = new LinkedHashMap<>(); private final List<AutoConfigurationEntry> autoConfigurationEntries = new ArrayList<>(); @Override public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) { Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector, () -> String.format("Only %s implementations are supported, got %s", AutoConfigurationImportSelector.class.getSimpleName(), deferredImportSelector.getClass().getName())); AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector) .getAutoConfigurationEntry(annotationMetadata); this.autoConfigurationEntries.add(autoConfigurationEntry); for (String importClassName : autoConfigurationEntry.getConfigurations()) { this.entries.putIfAbsent(importClassName, annotationMetadata); } } @Override public Iterable<Entry> selectImports() { if (this.autoConfigurationEntries.isEmpty()) { return Collections.emptyList(); } Set<String> allExclusions = this.autoConfigurationEntries.stream() .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet()); Set<String> processedConfigurations = this.autoConfigurationEntries.stream() .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream) .collect(Collectors.toCollection(LinkedHashSet::new)); processedConfigurations.removeAll(allExclusions); return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream() .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName)) .collect(Collectors.toList()); } }
最后看下DeferredImportSelectorGroupingHandler的register方法和processGroupImports方法
groupings属性
handler会处理所有的DeferredImportSelector,这个map按分组保存了DeferredImportSelector
key:如果DeferredImportSelector的group不为null,则key是group的Class对象;如果group是null,则key是该DeferredImportSelectorHolder对象。key本身没有作用,仅仅是通过key对所有的DeferredImportSelector分个组,后续对groups.values()进行遍历
value:是DeferredImportSelectorGrouping对象
private class DeferredImportSelectorGroupingHandler { private final Map<Object, DeferredImportSelectorGrouping> groupings = new LinkedHashMap<>(); private final Map<AnnotationMetadata, ConfigurationClass> configurationClasses = new HashMap<>(); // 将DeferredImportSelector进行分组,并创建DeferredImportSelectorGrouping public void register(DeferredImportSelectorHolder deferredImport) { Class<? extends Group> group = deferredImport.getImportSelector().getImportGroup(); DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent( (group != null ? group : deferredImport), key -> new DeferredImportSelectorGrouping(createGroup(group))); grouping.add(deferredImport); this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(), deferredImport.getConfigurationClass()); } public void processGroupImports() { // 对分好组的DeferredImportSelector分组处理 for (DeferredImportSelectorGrouping grouping : this.groupings.values()) { Predicate<String> exclusionFilter = grouping.getCandidateFilter(); // 调用了DeferredImportSelectorGrouping#getImports方法。如上,里面调用了 // group#process、group#selectImports,通过Group的特定化逻辑获取到了这一组 // DeferredImportSelector import的类。然后forEach对所有的类通过processImports // 处理 grouping.getImports().forEach(entry -> { ConfigurationClass configurationClass = this.configurationClasses.get(entry.getMetadata()); try { processImports(configurationClass, asSourceClass(configurationClass, exclusionFilter), Collections.singleton(asSourceClass(entry.getImportClassName(), exclusionFilter)), exclusionFilter, false); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (Throwable ex) { throw new BeanDefinitionStoreException( "Failed to process import candidates for configuration class [" + configurationClass.getMetadata().getClassName() + "]", ex); } }); } } // 实例化group,如果DeferredImportSelector指定了Group类,则用指定的类实例化,否则是默认的 // DefaultDeferredImportSelectorGroup private Group createGroup(@Nullable Class<? extends Group> type) { Class<? extends Group> effectiveType = (type != null ? type : DefaultDeferredImportSelectorGroup.class); return ParserStrategyUtils.instantiateClass(effectiveType, Group.class, ConfigurationClassParser.this.environment, ConfigurationClassParser.this.resourceLoader, ConfigurationClassParser.this.registry); } }
parse的过程中,有几个地方导入的类会暂存在configClass中,再由ConfigurationClassBeanDefinitionReader load进beanFactory
1、processImports过程中,遇到ImportBeanDefinitionRegistrar
else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // Candidate class is an ImportBeanDefinitionRegistrar -> // delegate to it to register additional bean definitions Class<?> candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry); configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); }
private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) { registrars.forEach((registrar, metadata) -> registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator)); }
2、@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); } }
如果@ImportResource注解指定了BeanDefinitionReader类名,则根据配置文件后缀使用GroovyBeanDefinitionReader、XmlBeanDefinitionReader,使用reader来load
private void loadBeanDefinitionsFromImportedResources( Map<String, Class<? extends BeanDefinitionReader>> importedResources) { Map<Class<?>, BeanDefinitionReader> readerInstanceCache = new HashMap<>(); importedResources.forEach((resource, readerClass) -> { // Default reader selection necessary? if (BeanDefinitionReader.class == readerClass) { if (StringUtils.endsWithIgnoreCase(resource, ".groovy")) { // When clearly asking for Groovy, that's what they'll get... readerClass = GroovyBeanDefinitionReader.class; } else if (shouldIgnoreXml) { throw new UnsupportedOperationException("XML support disabled"); } else { // Primarily ".xml" files but for any other extension as well readerClass = XmlBeanDefinitionReader.class; } } BeanDefinitionReader reader = readerInstanceCache.get(readerClass); if (reader == null) { try { // Instantiate the specified BeanDefinitionReader reader = readerClass.getConstructor(BeanDefinitionRegistry.class).newInstance(this.registry); // Delegate the current ResourceLoader to it if possible if (reader instanceof AbstractBeanDefinitionReader) { AbstractBeanDefinitionReader abdr = ((AbstractBeanDefinitionReader) reader); abdr.setResourceLoader(this.resourceLoader); abdr.setEnvironment(this.environment); } readerInstanceCache.put(readerClass, reader); } catch (Throwable ex) { throw new IllegalStateException( "Could not instantiate BeanDefinitionReader class [" + readerClass.getName() + "]"); } } // TODO SPR-6310: qualify relative path locations as done in AbstractContextLoader.modifyLocations reader.loadBeanDefinitions(resource); }); }
3、@Bean
Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); for (MethodMetadata methodMetadata : beanMethods) { configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); }