在分析Spring 容器建立過程時,咱們知道容器默認會加載一些後置處理器PostPRocessor,以AnnotationConfigApplicationContext爲例,在構造函數中初始化reader時,加載默認後置處理器。其中 ConfigurationClassPostProcessor這個後置處理器專門處理帶有@Configuration註解的類,ConfigurationClassPostProcessor後置處理實現了BeanDefinitionRegistryPostProcessor接口和PriorityOrdered接口,因此會在容器初始化refres()方法中執行後置處理器時優先執行,主要負責解析全部@Configuration標籤類,並將Bean定義註冊到容器中。java
BeanDefinitionRegistryPostProcessor解析配置類過程:spring
1 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { 2 //生成惟一標識,用於重複處理驗證 3 int registryId = System.identityHashCode(registry); 4 if (this.registriesPostProcessed.contains(registryId)) { 5 throw new IllegalStateException( 6 "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); 7 } 8 if (this.factoriesPostProcessed.contains(registryId)) { 9 throw new IllegalStateException( 10 "postProcessBeanFactory already called on this post-processor against " + registry); 11 } 12 this.registriesPostProcessed.add(registryId); 13 //解析Java類配置bean 14 processConfigBeanDefinitions(registry); 15 }
processConfigBeanDefinitions(registry)處理邏輯:
1 public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { 2 List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); 3 //全部已經註冊的bean 4 String[] candidateNames = registry.getBeanDefinitionNames(); 5 //遍歷bean定義信息 6 for (String beanName : candidateNames) { 7 BeanDefinition beanDef = registry.getBeanDefinition(beanName); 8 if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || 9 ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { 10 if (logger.isDebugEnabled()) { 11 logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); 12 } 13 } 14 //若是當前的bean是Javabean配置類(含有@Configuration註解的類),則加入到集合configCandidates中, 15 else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { 16 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); 17 } 18 } 19 20 // Return immediately if no @Configuration classes were found 21 // 沒有@Configuration註解的類,直接退出 22 if (configCandidates.isEmpty()) { 23 return; 24 } 25 26 // 多個Java配置類,按@Ordered註解排序 27 configCandidates.sort((bd1, bd2) -> { 28 int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); 29 int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); 30 return Integer.compare(i1, i2); 31 }); 32 33 // Detect any custom bean name generation strategy supplied through the enclosing application context 34 SingletonBeanRegistry sbr = null; 35 if (registry instanceof SingletonBeanRegistry) { 36 sbr = (SingletonBeanRegistry) registry; 37 if (!this.localBeanNameGeneratorSet) { 38 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); 39 if (generator != null) { 40 this.componentScanBeanNameGenerator = generator; 41 this.importBeanNameGenerator = generator; 42 } 43 } 44 } 45 46 if (this.environment == null) { 47 this.environment = new StandardEnvironment(); 48 } 49 50 // Parse each @Configuration class 51 //初始化一個ConfigurationClassParser解析器,能夠解析@Congiguration配置類 52 ConfigurationClassParser parser = new ConfigurationClassParser( 53 this.metadataReaderFactory, this.problemReporter, this.environment, 54 this.resourceLoader, this.componentScanBeanNameGenerator, registry); 55 56 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); 57 Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); 58 do { 59 //1.解析Java配置類 60 parser.parse(candidates); 61 //主要校驗配置類不能使用final修飾符(CGLIB代理是生成一個子類,所以原先的類不能使用final修飾) 62 parser.validate(); 63 64 //排除已處理過的配置類 65 Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); 66 configClasses.removeAll(alreadyParsed); 67 68 // Read the model and create bean definitions based on its content 69 if (this.reader == null) { 70 this.reader = new ConfigurationClassBeanDefinitionReader( 71 registry, this.sourceExtractor, this.resourceLoader, this.environment, 72 this.importBeanNameGenerator, parser.getImportRegistry()); 73 } 74 //2.加載bean定義信息,主要實現將@Configuration @Import @ImportResource @ImportRegistrar註冊爲bean 75 this.reader.loadBeanDefinitions(configClasses); 76 alreadyParsed.addAll(configClasses); 77 //清空已處理的配置類 78 candidates.clear(); 79 //再次獲取容器中bean定義數量 若是大於 以前獲取的bean定義數量,則說明有新的bean註冊到容器中,須要再次解析 80 if (registry.getBeanDefinitionCount() > candidateNames.length) { 81 String[] newCandidateNames = registry.getBeanDefinitionNames(); 82 Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); 83 Set<String> alreadyParsedClasses = new HashSet<>(); 84 for (ConfigurationClass configurationClass : alreadyParsed) { 85 alreadyParsedClasses.add(configurationClass.getMetadata().getClassName()); 86 } 87 for (String candidateName : newCandidateNames) { 88 if (!oldCandidateNames.contains(candidateName)) { 89 BeanDefinition bd = registry.getBeanDefinition(candidateName); 90 //新註冊的bean若是也是@Configuration配置類,則添加到數據,等待解析 91 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) && 92 !alreadyParsedClasses.contains(bd.getBeanClassName())) { 93 candidates.add(new BeanDefinitionHolder(bd, candidateName)); 94 } 95 } 96 } 97 candidateNames = newCandidateNames; 98 } 99 } 100 while (!candidates.isEmpty()); 101 102 // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes 103 if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { 104 sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); 105 } 106 107 if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { 108 // Clear cache in externally provided MetadataReaderFactory; this is a no-op 109 // for a shared cache since it'll be cleared by the ApplicationContext. 110 ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); 111 } 112 }
parser.parse(candidates)方法最終調用processConfigurationClass方法來處理@Configuration配置類,ConfigurationClassParser. processConfigurationClass()方法實現代碼以下:app
1 protected void processConfigurationClass(ConfigurationClass configClass) throws IOException { 2 //判斷是否須要解析 3 if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) { 4 return; 5 } 6 //判斷同一個配置類是否重複加載過,若是重複加載過,則合併,不然從集合中移除舊的配置類,後續邏輯將處理新的配置類 7 ConfigurationClass existingClass = this.configurationClasses.get(configClass); 8 if (existingClass != null) { 9 if (configClass.isImported()) { 10 if (existingClass.isImported()) { 11 existingClass.mergeImportedBy(configClass); 12 } 13 // Otherwise ignore new imported config class; existing non-imported class overrides it. 14 return; 15 } 16 else { 17 // Explicit bean definition found, probably replacing an import. 18 // Let's remove the old one and go with the new one. 19 this.configurationClasses.remove(configClass); 20 this.knownSuperclasses.values().removeIf(configClass::equals); 21 } 22 } 23 24 // Recursively process the configuration class and its superclass hierarchy. 25 SourceClass sourceClass = asSourceClass(configClass); 26 do { 27 //【真正解析配置類】 28 sourceClass = doProcessConfigurationClass(configClass, sourceClass); 29 } 30 while (sourceClass != null); 31 //再次添加到到集合中 32 this.configurationClasses.put(configClass, configClass); 33 }
doProcessConfigurationClass方法主要實現從配置類中解析全部bean,包括處理內部類,父類以及各類註解ide
ConfigurationClassParser. doProcessConfigurationClass()解析配置類邏輯以下:函數
1 protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass) 2 throws IOException { 3 4 //遞歸處理任何成員(嵌套)類 5 processMemberClasses(configClass, sourceClass); 6 7 // 處理@PropertySource註解 8 for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable( 9 sourceClass.getMetadata(), PropertySources.class, 10 org.springframework.context.annotation.PropertySource.class)) { 11 if (this.environment instanceof ConfigurableEnvironment) { 12 processPropertySource(propertySource); 13 } 14 else { 15 logger.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() + 16 "]. Reason: Environment must implement ConfigurableEnvironment"); 17 } 18 } 19 20 // 處理@ComponentScan 21 //獲取@ComponentScan註解信息 22 Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable( 23 sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class); 24 if (!componentScans.isEmpty() && 25 !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) { 26 for (AnnotationAttributes componentScan : componentScans) { 27 28 // 按@CmponentScan註解掃描bean 29 Set<BeanDefinitionHolder> scannedBeanDefinitions = 30 this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName()); 31 // 遍歷掃描出的bean定義是不是配置類bean 32 for (BeanDefinitionHolder holder : scannedBeanDefinitions) { 33 BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition(); 34 if (bdCand == null) { 35 bdCand = holder.getBeanDefinition(); 36 } 37 //若果掃描出的bean定義是配置類(含有@COnfiguration),則繼續調用parse方法,內部再次調用doProcessConfigurationClas(),遞歸解析 38 if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) { 39 parse(bdCand.getBeanClassName(), holder.getBeanName()); 40 } 41 } 42 } 43 } 44 45 //處理@Import註解 46 processImports(configClass, sourceClass, getImports(sourceClass), true); 47 48 //處理@ImportResource註解 49 AnnotationAttributes importResource = 50 AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class); 51 if (importResource != null) { 52 String[] resources = importResource.getStringArray("locations"); 53 Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader"); 54 for (String resource : resources) { 55 String resolvedResource = this.environment.resolveRequiredPlaceholders(resource); 56 configClass.addImportedResource(resolvedResource, readerClass); 57 } 58 } 59 60 //處理@Bean註解 61 Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass); 62 for (MethodMetadata methodMetadata : beanMethods) { 63 //將解析出的全部@Bean註解方法添加到configClass配置類信息中 64 configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass)); 65 } 66 67 //處理接口中全部添加@Bean註解的方法,內部經過遍歷全部接口,解析獲得@Bean註解方法,並添加到configClass配置類信息中 68 processInterfaces(configClass, sourceClass); 69 70 // 若是有父類,則返回父類,遞歸執行doProcessConfigurationClass()解析父類 71 if (sourceClass.getMetadata().hasSuperClass()) { 72 String superclass = sourceClass.getMetadata().getSuperClassName(); 73 if (superclass != null && !superclass.startsWith("java") && 74 !this.knownSuperclasses.containsKey(superclass)) { 75 this.knownSuperclasses.put(superclass, configClass); 76 // Superclass found, return its annotation metadata and recurse 77 return sourceClass.getSuperClass(); 78 } 79 } 80 81 // No superclass -> processing is complete 82 return null; 83 }
下面看兩個很重要的註解@Bean和@ComponentScan的實現過程post
Set<BeanDefinitionHolder> scannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
@ComponentScan註解解析,從上面的代碼能夠看出@ComponentScan註解解析經過調用ComponentScanAnnotationParser的parse方法完成,而parse()方法內部處理了一些scanner屬性(過濾器設置)和basePackages包名處理,最終經過調用ClassPathBeanDefinitionScanner.doScan方法實現掃面工做ui
1 public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) { 2 ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry, 3 componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); 4 5 Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator"); 6 boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass); 7 scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator : 8 BeanUtils.instantiateClass(generatorClass)); 9 10 ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy"); 11 if (scopedProxyMode != ScopedProxyMode.DEFAULT) { 12 scanner.setScopedProxyMode(scopedProxyMode); 13 } 14 else { 15 Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver"); 16 scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass)); 17 } 18 19 scanner.setResourcePattern(componentScan.getString("resourcePattern")); 20 21 for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) { 22 for (TypeFilter typeFilter : typeFiltersFor(filter)) { 23 scanner.addIncludeFilter(typeFilter); 24 } 25 } 26 for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) { 27 for (TypeFilter typeFilter : typeFiltersFor(filter)) { 28 scanner.addExcludeFilter(typeFilter); 29 } 30 } 31 32 boolean lazyInit = componentScan.getBoolean("lazyInit"); 33 if (lazyInit) { 34 scanner.getBeanDefinitionDefaults().setLazyInit(true); 35 } 36 37 Set<String> basePackages = new LinkedHashSet<>(); 38 String[] basePackagesArray = componentScan.getStringArray("basePackages"); 39 for (String pkg : basePackagesArray) { 40 String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg), 41 ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); 42 Collections.addAll(basePackages, tokenized); 43 } 44 for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) { 45 basePackages.add(ClassUtils.getPackageName(clazz)); 46 } 47 if (basePackages.isEmpty()) { 48 basePackages.add(ClassUtils.getPackageName(declaringClass)); 49 } 50 51 scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) { 52 @Override 53 protected boolean matchClassName(String className) { 54 return declaringClass.equals(className); 55 } 56 }); 57 return scanner.doScan(StringUtils.toStringArray(basePackages)); 58 }
doScan掃描basePackages下全部beanthis
1 protected Set<BeanDefinitionHolder> doScan(String... basePackages) { 2 Assert.notEmpty(basePackages, "At least one base package must be specified"); 3 Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>(); 4 for (String basePackage : basePackages) { 5 //根據basePackage加載包下全部java文件,並掃描出全部bean組件, findCandidateComponents方法內部調用ClassPathScanningCandidateComponentProvider.scanCandidateComponents(backPackages) 6 Set<BeanDefinition> candidates = findCandidateComponents(basePackage); 7 //遍歷beandefition 8 for (BeanDefinition candidate : candidates) { 9 //解析做用域Scope 10 ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); 11 candidate.setScope(scopeMetadata.getScopeName()); 12 String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); 13 // 14 if (candidate instanceof AbstractBeanDefinition) { 15 postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName); 16 } 17 //通用註解解析到candidate結構中,主要是處理Lazy, primary DependsOn, Role ,Description這五個註解 18 if (candidate instanceof AnnotatedBeanDefinition) { 19 AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate); 20 } 21 //檢查當前bean是否已經註冊,不存在則註冊 22 if (checkCandidate(beanName, candidate)) { 23 BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); 24 definitionHolder = 25 AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); 26 beanDefinitions.add(definitionHolder); 27 // 註冊到ioc容器中,主要是一些@Component組件,@Bean註解方法並無在此處註冊, definitionHolder: beanname和beandefinition 鍵值對 28 registerBeanDefinition(definitionHolder, this.registry); 29 } 30 } 31 } 32 return beanDefinitions; 33 }
ClassPathBeanDefinitionScanner.scanCandidateComponents實現bean定義信息掃描lua
1 private Set<BeanDefinition> scanCandidateComponents(String basePackage) { 2 Set<BeanDefinition> candidates = new LinkedHashSet<>(); 3 try { 4 // @ComponentScan("com.sl.springlearning.extension")包路徑處理:packageSearchPath = classpath*:com/sl/springlearning/extension/**/*.class 5 String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + 6 resolveBasePackage(basePackage) + '/' + this.resourcePattern; 7 //獲取當前包下全部的class文件 8 Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath); 9 boolean traceEnabled = logger.isTraceEnabled(); 10 boolean debugEnabled = logger.isDebugEnabled(); 11 for (Resource resource : resources) { 12 if (traceEnabled) { 13 logger.trace("Scanning " + resource); 14 } 15 if (resource.isReadable()) { 16 try { 17 MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource); 18 //按照scanner過濾器過濾,好比配置類自己將被果過濾掉,沒有@Component等組件註解的類將過濾掉 19 if (isCandidateComponent(metadataReader)) { 20 ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); 21 sbd.setResource(resource); 22 sbd.setSource(resource); 23 if (isCandidateComponent(sbd)) { 24 if (debugEnabled) { 25 logger.debug("Identified candidate component class: " + resource); 26 } 27 candidates.add(sbd); 28 } 29 else { 30 if (debugEnabled) { 31 logger.debug("Ignored because not a concrete top-level class: " + resource); 32 } 33 } 34 } 35 else { 36 if (traceEnabled) { 37 logger.trace("Ignored because not matching any filter: " + resource); 38 } 39 } 40 } 41 catch (Throwable ex) { 42 throw new BeanDefinitionStoreException( 43 "Failed to read candidate component class: " + resource, ex); 44 } 45 } 46 else { 47 if (traceEnabled) { 48 logger.trace("Ignored because not readable: " + resource); 49 } 50 } 51 } 52 } 53 catch (IOException ex) { 54 throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex); 55 } 56 return candidates; 57 }
retrieveBeanMethodMetadata方法實現了@Bean方法的解析,並未將實現bean實例的建立。spa
1 private Set<MethodMetadata> retrieveBeanMethodMetadata(SourceClass sourceClass) { 2 AnnotationMetadata original = sourceClass.getMetadata(); 3 //獲取全部@Bean註解的方法 4 Set<MethodMetadata> beanMethods = original.getAnnotatedMethods(Bean.class.getName()); 5 // 若是配置類中有多個@Bean註解的方法,則排序 6 if (beanMethods.size() > 1 && original instanceof StandardAnnotationMetadata) { 7 // Try reading the class file via ASM for deterministic declaration order... 8 // Unfortunately, the JVM's standard reflection returns methods in arbitrary 9 // order, even between different runs of the same application on the same JVM. 10 try { 11 AnnotationMetadata asm = 12 this.metadataReaderFactory.getMetadataReader(original.getClassName()).getAnnotationMetadata(); 13 Set<MethodMetadata> asmMethods = asm.getAnnotatedMethods(Bean.class.getName()); 14 if (asmMethods.size() >= beanMethods.size()) { 15 Set<MethodMetadata> selectedMethods = new LinkedHashSet<>(asmMethods.size()); 16 for (MethodMetadata asmMethod : asmMethods) { 17 for (MethodMetadata beanMethod : beanMethods) { 18 if (beanMethod.getMethodName().equals(asmMethod.getMethodName())) { 19 selectedMethods.add(beanMethod); 20 break; 21 } 22 } 23 } 24 if (selectedMethods.size() == beanMethods.size()) { 25 // All reflection-detected methods found in ASM method set -> proceed 26 beanMethods = selectedMethods; 27 } 28 } 29 } 30 catch (IOException ex) { 31 logger.debug("Failed to read class file via ASM for determining @Bean method order", ex); 32 // No worries, let's continue with the reflection metadata we started with... 33 } 34 } 35 return beanMethods; 36 }
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法的功能就是將以前解析出的configClasses配置類信息中全部配置相關的信息添加到spring的bean定義,主要是配置類中的@Bean註解方法,配置類@ImportResource和@Import(實現ImportBeanDefinitionRegistrar接口方式)的bean註冊
ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()方法 實現邏輯以下:
1 public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) { 2 TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator(); 3 for (ConfigurationClass configClass : configurationModel) { 4 loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator); 5 } 6 }
1 private void loadBeanDefinitionsForConfigurationClass( 2 ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) { 3 if (trackedConditionEvaluator.shouldSkip(configClass)) { 4 String beanName = configClass.getBeanName(); 5 if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) { 6 this.registry.removeBeanDefinition(beanName); 7 } 8 this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName()); 9 return; 10 } 11 12 if (configClass.isImported()) { 13 registerBeanDefinitionForImportedConfigurationClass(configClass); 14 } 15 //將@Bean方法註冊爲bean 16 for (BeanMethod beanMethod : configClass.getBeanMethods()) { 17 loadBeanDefinitionsForBeanMethod(beanMethod); 18 } 19 //將configClass中中ImportResource指定的資源註冊爲bean 20 loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); 21 //將configClass中ImportedRegistrar註冊爲bean 22 loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars()); 23 }
處理邏輯理了一遍後,看一下ConfigurationClassPostProcessor處理器解析@configuration配置類主要過程:
1. Spring容器初始化時註冊默認後置處理器ConfigurationClassPostProcessor
2. Spring容器初始化執行refresh()方法中調用ConfigurationClassPostProcessor
3. ConfigurationClassPostProcessor處理器藉助ConfigurationClassParser完成配置類解析
4. ConfigurationClassParser配置內解析過程當中完成嵌套的MemberClass、@PropertySource註解、@ComponentScan註解(掃描package下的全部Class並進行迭代解析,主要是@Component組件解析及註冊)、@ImportResource、@Bean等處理
5. 完成@Bean註冊, @ImportResource指定bean的註冊以及@Import(實現ImportBeanDefinitionRegistrar接口方式)的bean註冊